├── .editorconfig ├── .github └── FUNDING.yml ├── .gitignore ├── Directory.Build.props ├── Directory.Build.targets ├── Directory.Packages.props ├── GitExtensions.PluginManager.sln ├── GitExtensions.settings ├── LICENSE.md ├── README.md ├── appveyor.yml ├── assets └── screenshot-search.png ├── data └── NuGetFeed │ ├── CustomPackage.5.0.0.nupkg │ ├── GitExtensions.Extensibility.0.1.0.nupkg │ ├── GitExtensions.Extensibility.0.2.0.nupkg │ ├── PluginA.1.0.0.nupkg │ ├── PluginA.1.1.0.nupkg │ ├── PluginB.1.0.0.nupkg │ ├── PluginB.2.0.0.nupkg │ └── PluginC.1.0.0.nupkg ├── src ├── GitExtensions.PluginManager │ ├── ArgsFix.cs │ ├── GitExtensions.PluginManager.csproj │ ├── GitExtensions.PluginManager.csproj.user │ ├── GitExtensions.PluginManager.nuspec │ ├── Plugin.cs │ ├── PluginSettings.cs │ ├── Project.Publish.targets │ ├── Properties │ │ ├── Resources.Designer.cs │ │ ├── Resources.resx │ │ └── launchSettings.json │ └── Resources │ │ └── box-search-result.png ├── PackageManager.Cli │ ├── AllPackageSourceSelector.cs │ ├── Args.cs │ ├── PackageManager.Cli.csproj │ ├── Program.cs │ ├── SelfUpdateService.IApplication.cs │ └── SelfUpdateService.IArgs.cs ├── PackageManager.NuGet │ ├── Logging │ │ └── NuGetLogger.cs │ ├── Models │ │ ├── InvalidPackageSourceImplementationException.cs │ │ ├── NuGetInstalledPackage.cs │ │ ├── NuGetPackage.cs │ │ ├── NuGetPackageContent.AnyFrameworkFilter.cs │ │ ├── NuGetPackageContent.IFrameworkFilter.cs │ │ ├── NuGetPackageContent.cs │ │ ├── NuGetPackageIdentity.cs │ │ ├── NuGetPackageSource.cs │ │ ├── NuGetPackageSourceBuilder.cs │ │ ├── NuGetPackageSourceCollection.cs │ │ └── NuGetPackageVersionComparer.cs │ ├── PackageManager.NuGet.csproj │ └── Services │ │ ├── EmptyNuGetSearchTermTransformer.cs │ │ ├── INuGetPackageFilter.cs │ │ ├── INuGetSearchTermTransformer.cs │ │ ├── NuGetInstallService.cs │ │ ├── NuGetPackageContentService.cs │ │ ├── NuGetPackageFilterResult.cs │ │ ├── NuGetPackageVersionService.cs │ │ ├── NuGetSearchService.cs │ │ ├── NuGetSearchTerm.cs │ │ ├── NuGetSourceRepositoryFactory.cs │ │ └── OkNuGetPackageFilter.cs ├── PackageManager.UI │ ├── App.xaml │ ├── App.xaml.cs │ ├── Args.Partial.cs │ ├── Args.cs │ ├── Exceptions │ │ ├── MessageExceptionHandler.cs │ │ ├── NuGetFatalProtocolExceptionHandler.cs │ │ ├── PackageInstallExceptionHandler.cs │ │ ├── RestartAsAdministratorCancelledExceptionHandler.cs │ │ ├── ShutdownExceptionHandler.cs │ │ └── UnauthorizedExceptionHandler.cs │ ├── Logging │ │ └── Serialization │ │ │ └── MemoryLogSerializer.cs │ ├── Models │ │ ├── NuGetFrameworkFilter.cs │ │ └── SelfPackage.cs │ ├── PackageManager.UI.csproj │ ├── Program.cs │ ├── Properties │ │ ├── Resources.Designer.cs │ │ ├── Resources.resx │ │ ├── Settings.Designer.cs │ │ ├── Settings.settings │ │ └── VersionInfo.cs │ ├── Services │ │ ├── DependencyNuGetPackageFilter.cs │ │ ├── Navigator.cs │ │ ├── ProcessService.IApplication.cs │ │ ├── ProcessService.ProcessKillContext.cs │ │ ├── ProcessService.cs │ │ ├── RestartAsAdministratorCancelledException.cs │ │ ├── SelfUpdateService.IApplication.cs │ │ ├── SelfUpdateService.IArgs.cs │ │ ├── SelfUpdateService.cs │ │ └── TagsNuGetSearchTermTransformer.cs │ └── Views │ │ ├── Assets │ │ ├── baseline_add_black_18dp.png │ │ ├── baseline_arrow_downward_black_18dp.png │ │ ├── baseline_arrow_upward_black_18dp.png │ │ ├── baseline_chevron_left_black_18dp.png │ │ ├── baseline_chevron_right_black_18dp.png │ │ ├── baseline_clear_black_18dp.png │ │ ├── baseline_done_black_18dp.png │ │ ├── baseline_edit_black_18dp.png │ │ ├── baseline_refresh_black_18dp.png │ │ ├── baseline_search_black_18dp.png │ │ ├── box-search-result.ico │ │ ├── box-search-result.png │ │ ├── default-package-icon.png │ │ └── settings.png │ │ ├── Browser.xaml │ │ ├── Browser.xaml.cs │ │ ├── Controls │ │ ├── Button.cs │ │ ├── CompatibilityLabel.cs │ │ └── TabControl.cs │ │ ├── Converters │ │ ├── BoolConverter.cs │ │ ├── CuttingConverter.cs │ │ ├── DropNewLineConverter.cs │ │ ├── FirstNotNullMultiConverter.cs │ │ ├── FormatConverter.cs │ │ ├── NullConverter.cs │ │ ├── NullValueConverter.cs │ │ ├── SelfPackageConverter.cs │ │ └── ValidUrlToTrueConverter.cs │ │ ├── DesignData │ │ ├── MockInstallService.cs │ │ ├── MockInstalledPackage.cs │ │ ├── MockPackage.cs │ │ ├── MockPackageSource.cs │ │ ├── MockPackageSourceBuilder.cs │ │ ├── MockPackageSourceCollection.cs │ │ ├── MockPackageSourceProvider.cs │ │ ├── MockSearchService.cs │ │ ├── MockSelfUpdateService.cs │ │ └── ViewModelLocator.cs │ │ ├── IAutoFocus.cs │ │ ├── Installed.xaml │ │ ├── Installed.xaml.cs │ │ ├── Loading.xaml │ │ ├── Loading.xaml.cs │ │ ├── LogWindow.xaml │ │ ├── LogWindow.xaml.cs │ │ ├── MainWindow.xaml │ │ ├── MainWindow.xaml.cs │ │ ├── PackageDetail.xaml │ │ ├── PackageDetail.xaml.cs │ │ ├── PackageName.xaml │ │ ├── PackageName.xaml.cs │ │ ├── PackageSourceWindow.xaml │ │ ├── PackageSourceWindow.xaml.cs │ │ ├── Updates.xaml │ │ └── Updates.xaml.cs └── PackageManager │ ├── Models │ ├── IInstalledPackage.cs │ ├── IPackage.cs │ ├── IPackageContent.cs │ ├── IPackageIdentity.cs │ ├── IPackageSource.cs │ ├── IPackageSourceBuilder.cs │ ├── IPackageSourceCollection.cs │ ├── IPackageSourceProvider.cs │ ├── PackageFileExtractionException.cs │ ├── PackageFileRemovalException.cs │ └── PackageIdentityExtensions.cs │ ├── PackageManager.csproj │ ├── Services │ ├── IInstallService.cs │ ├── ISearchService.cs │ ├── ISelfUpdateService.cs │ ├── SearchOptions.cs │ └── SelfPackageConfiguration.cs │ └── ViewModels │ ├── BrowserViewModel.cs │ ├── Commands │ ├── CancelCommand.cs │ ├── InstallCommand.cs │ ├── MoveCommand.cs │ ├── RefreshInstalledCommand.cs │ ├── RefreshUpdatesCommand.cs │ ├── ReinstallCommand.cs │ ├── RemoveSourceCommand.cs │ ├── SaveSourceCommand.cs │ ├── SearchCommand.cs │ ├── UninstallAllCommand.IViewModel.cs │ ├── UninstallAllCommand.cs │ ├── UninstallCommand.cs │ ├── UpdateAllCommand.IViewModel.cs │ ├── UpdateAllCommand.cs │ └── UpdateCommand.cs │ ├── IPackageOptions.cs │ ├── IPackageSourceSelector.cs │ ├── InstalledViewModel.cs │ ├── MainViewModel.cs │ ├── PackageSourceSelectorViewModel.cs │ ├── PackageSourceViewModel.cs │ ├── PackageUpdateViewModel.cs │ ├── PackageViewModel.cs │ ├── PagingViewModel.cs │ └── UpdatesViewModel.cs └── test ├── Directory.Build.props ├── Directory.Build.targets ├── PackageManager.NuGet.Tests ├── Models │ ├── TestPackageContent.cs │ └── TestPackageSourceCollection.cs ├── PackageManager.NuGet.Tests.csproj └── Services │ ├── InstallService.cs │ ├── SearchService.cs │ ├── TestInstallService.cs │ └── TestPackageSearchService.cs └── PackageManager.Tests ├── Arguments └── TestArgs.cs ├── PackageManager.Tests.csproj └── ViewModels └── Commands ├── CallCounter.cs ├── InstallService.cs ├── InstalledPackage.cs ├── Package.cs ├── PackageOptions.cs ├── SelfUpdateService.cs ├── TestCommands.cs ├── UninstallAllCommandViewModel.cs └── UpdateAllCommandViewModel.cs /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | open_collective: gitextensions 4 | custom: https://github.com/gitextensions/gitextensions/wiki 5 | -------------------------------------------------------------------------------- /Directory.Build.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net8.0-windows 5 | latest 6 | $(NoWarn);1573;1591;1712 7 | true 8 | true 9 | win-x86 10 | 11 | 12 | 13 | Git Extensions 14 | Git Extensions 15 | https://github.com/gitextensions/gitextensions.pluginmanager 16 | latest 17 | 0.0.0 18 | 0.0.0.1 19 | 0.0.0.1 20 | 0.0.0.1 21 | 0.0.0.1 22 | 23 | 24 | 25 | 26 | $([MSBuild]::NormalizeDirectory('$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildProjectDirectory), 'appveyor.yml'))')) 27 | 28 | $([MSBuild]::NormalizeDirectory('$(RepoRoot)', 'artifacts', '$(Configuration)')) 29 | $([MSBuild]::NormalizeDirectory('$(ArtifactsDir)', 'obj')) 30 | $([MSBuild]::NormalizeDirectory('$(ArtifactsDir)', 'bin')) 31 | $([MSBuild]::NormalizeDirectory('$(ArtifactsDir)', 'TestResults')) 32 | $([MSBuild]::NormalizeDirectory('$(ArtifactsDir)', 'tmp')) 33 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /Directory.Build.targets: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /Directory.Packages.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | true 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Git Extensions 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # GitExtensions.PluginManager 2 | NuGet based plugin manager for Git Extensions 3 | 4 | ![Preview](/assets/screenshot-search.png) 5 | 6 | Repository with some example plugins - https://www.myget.org/F/neptuo-gitextensions/api/v2.
7 | Nightly builds of PluginManager available at Appveyor - https://ci.appveyor.com/nuget/gitextensions-pluginmanager. 8 | 9 | ### Appveyor 10 | 11 | [![Build status](https://ci.appveyor.com/api/projects/status/cg2y7qojbugw7usg?svg=true)](https://ci.appveyor.com/project/gitextensions/gitextensions-pluginmanager) 12 | 13 | ### Browsing for packages 14 | PluginManager integrated into Git Extensions filters packages with dependency on `GitExtensions.Extensibility`. This package is right now a kind of meta package and it is used to mark nuget packages intended as Git Extensions plugins. 15 | 16 | We are heading to use the official nuget.org feed to distribute plugin packages, but there is a bug (#67) which prevents us from using it. 17 | Right now it is recommended to use https://www.myget.org/F/neptuo-gitextensions/api/v2. 18 | 19 | ### Command line arguments 20 | PluginManager is designed to be a reusable tool to manage plugins distributed as nuget packages. This repository contains an integration package for Git Extensins. 21 | As a standalone application, PluginManager supports these command line arguments: 22 | 23 | - `--path` (required) - A root path to a directory where to install packages. 24 | - `--selfpackageid` (optional) - A package id to indicate which package should be treated as a package for self update. 25 | - `--dependencies` (optional) - A comma separated list of package ids and versions that are required in package to be compatible (Eg. `GitExtensions.Extensibility-v3.0,TestA,TestB-v1`). 26 | - `--monikers` (optional) - A comma separated list of .NET framework monikers to filter package content during extraction (Eg. `net461,netstandard2.0`). 27 | - `--processnamestokillbeforechange` - A comma separated list of process names to be killed before any changes being processed (it is used to kill all instances on Git Extensions before installing/uninstalling dlls, that might be locked). 28 | 29 | ### Icons 30 | 31 | Some icons by Yusuke [Kamiyamane](http://p.yusukekamiyamane.com).
32 | Some other by [Material Design](https://material.io/tools/icons). 33 | -------------------------------------------------------------------------------- /assets/screenshot-search.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gitextensions/gitextensions.pluginmanager/daaf7af3ab2a895afc5dab4e494c585455a39924/assets/screenshot-search.png -------------------------------------------------------------------------------- /data/NuGetFeed/CustomPackage.5.0.0.nupkg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gitextensions/gitextensions.pluginmanager/daaf7af3ab2a895afc5dab4e494c585455a39924/data/NuGetFeed/CustomPackage.5.0.0.nupkg -------------------------------------------------------------------------------- /data/NuGetFeed/GitExtensions.Extensibility.0.1.0.nupkg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gitextensions/gitextensions.pluginmanager/daaf7af3ab2a895afc5dab4e494c585455a39924/data/NuGetFeed/GitExtensions.Extensibility.0.1.0.nupkg -------------------------------------------------------------------------------- /data/NuGetFeed/GitExtensions.Extensibility.0.2.0.nupkg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gitextensions/gitextensions.pluginmanager/daaf7af3ab2a895afc5dab4e494c585455a39924/data/NuGetFeed/GitExtensions.Extensibility.0.2.0.nupkg -------------------------------------------------------------------------------- /data/NuGetFeed/PluginA.1.0.0.nupkg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gitextensions/gitextensions.pluginmanager/daaf7af3ab2a895afc5dab4e494c585455a39924/data/NuGetFeed/PluginA.1.0.0.nupkg -------------------------------------------------------------------------------- /data/NuGetFeed/PluginA.1.1.0.nupkg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gitextensions/gitextensions.pluginmanager/daaf7af3ab2a895afc5dab4e494c585455a39924/data/NuGetFeed/PluginA.1.1.0.nupkg -------------------------------------------------------------------------------- /data/NuGetFeed/PluginB.1.0.0.nupkg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gitextensions/gitextensions.pluginmanager/daaf7af3ab2a895afc5dab4e494c585455a39924/data/NuGetFeed/PluginB.1.0.0.nupkg -------------------------------------------------------------------------------- /data/NuGetFeed/PluginB.2.0.0.nupkg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gitextensions/gitextensions.pluginmanager/daaf7af3ab2a895afc5dab4e494c585455a39924/data/NuGetFeed/PluginB.2.0.0.nupkg -------------------------------------------------------------------------------- /data/NuGetFeed/PluginC.1.0.0.nupkg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gitextensions/gitextensions.pluginmanager/daaf7af3ab2a895afc5dab4e494c585455a39924/data/NuGetFeed/PluginC.1.0.0.nupkg -------------------------------------------------------------------------------- /src/GitExtensions.PluginManager/ArgsFix.cs: -------------------------------------------------------------------------------- 1 | namespace Neptuo 2 | { 3 | public interface ICloneable 4 | { 5 | T Clone(); 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /src/GitExtensions.PluginManager/GitExtensions.PluginManager.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | true 6 | true 7 | NuGet-based Plugin Manager for Git Extensions 8 | GitExtensions 9 | https://github.com/gitextensions/gitextensions.pluginmanager 10 | OnOutputUpdated 11 | $(MSBuildThisFileDirectory)$(MSBuildProjectName).nuspec 12 | 1701;1702;NU5100;NU5101;NU5103;NU5128 13 | false 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | $(GitExtensionsPath)\GitExtensions.Extensibility.dll 29 | 30 | 31 | $(GitExtensionsPath)\GitUIPluginInterfaces.dll 32 | 33 | 34 | 35 | 36 | 38 | 39 | 40 | 41 | 42 | True 43 | True 44 | Resources.resx 45 | 46 | 47 | ResXFileCodeGenerator 48 | Resources.Designer.cs 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | -------------------------------------------------------------------------------- /src/GitExtensions.PluginManager/GitExtensions.PluginManager.csproj.user: -------------------------------------------------------------------------------- 1 |  2 | 3 | ..\..\..\gitextensions.shared 4 | latest 5 | AppVeyor 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /src/GitExtensions.PluginManager/GitExtensions.PluginManager.nuspec: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | $id$ 5 | $version$ 6 | $author$ 7 | $description$ 8 | $projectUrl$ 9 | $tags$ 10 | LICENSE.md 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /src/GitExtensions.PluginManager/PluginSettings.cs: -------------------------------------------------------------------------------- 1 | using GitExtensions.Extensibility.Settings; 2 | using System; 3 | using System.Collections; 4 | using System.Collections.Generic; 5 | 6 | namespace GitExtensions.PluginManager 7 | { 8 | internal class PluginSettings : IEnumerable 9 | { 10 | /// 11 | /// Gets a property holding if asking to close git extensions is required. 12 | /// 13 | public static BoolSetting CloseInstancesProperty { get; } = new BoolSetting("CloseInstances", "Close all instances of Git Extensions before starting Plugin Manager", false); 14 | 15 | private readonly SettingsSource source; 16 | 17 | /// 18 | /// Gets current value of . 19 | /// 20 | public bool CloseInstances => source.GetBool(CloseInstancesProperty.Name, CloseInstancesProperty.DefaultValue); 21 | 22 | public PluginSettings(SettingsSource source) 23 | { 24 | this.source = source ?? throw new ArgumentNullException(nameof(source)); 25 | } 26 | 27 | #region IEnumerable 28 | 29 | private static readonly List properties; 30 | 31 | public static bool HasProperties => properties.Count > 0; 32 | 33 | static PluginSettings() 34 | { 35 | properties = new List(1) 36 | { 37 | CloseInstancesProperty 38 | }; 39 | } 40 | 41 | public IEnumerator GetEnumerator() 42 | => properties.GetEnumerator(); 43 | 44 | IEnumerator IEnumerable.GetEnumerator() 45 | => GetEnumerator(); 46 | 47 | #endregion 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/GitExtensions.PluginManager/Properties/Resources.Designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // Runtime Version:4.0.30319.42000 5 | // 6 | // Changes to this file may cause incorrect behavior and will be lost if 7 | // the code is regenerated. 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | namespace GitExtensions.PluginManager.Properties { 12 | using System; 13 | 14 | 15 | /// 16 | /// A strongly-typed resource class, for looking up localized strings, etc. 17 | /// 18 | // This class was auto-generated by the StronglyTypedResourceBuilder 19 | // class via a tool like ResGen or Visual Studio. 20 | // To add or remove a member, edit your .ResX file then rerun ResGen 21 | // with the /str option, or rebuild your VS project. 22 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "15.0.0.0")] 23 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 24 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] 25 | internal class Resources { 26 | 27 | private static global::System.Resources.ResourceManager resourceMan; 28 | 29 | private static global::System.Globalization.CultureInfo resourceCulture; 30 | 31 | [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] 32 | internal Resources() { 33 | } 34 | 35 | /// 36 | /// Returns the cached ResourceManager instance used by this class. 37 | /// 38 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] 39 | internal static global::System.Resources.ResourceManager ResourceManager { 40 | get { 41 | if (object.ReferenceEquals(resourceMan, null)) { 42 | global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("GitExtensions.PluginManager.Properties.Resources", typeof(Resources).Assembly); 43 | resourceMan = temp; 44 | } 45 | return resourceMan; 46 | } 47 | } 48 | 49 | /// 50 | /// Overrides the current thread's CurrentUICulture property for all 51 | /// resource lookups using this strongly typed resource class. 52 | /// 53 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] 54 | internal static global::System.Globalization.CultureInfo Culture { 55 | get { 56 | return resourceCulture; 57 | } 58 | set { 59 | resourceCulture = value; 60 | } 61 | } 62 | 63 | /// 64 | /// Looks up a localized resource of type System.Drawing.Bitmap. 65 | /// 66 | internal static System.Drawing.Bitmap Icon { 67 | get { 68 | object obj = ResourceManager.GetObject("Icon", resourceCulture); 69 | return ((System.Drawing.Bitmap)(obj)); 70 | } 71 | } 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /src/GitExtensions.PluginManager/Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "profiles": { 3 | "GitExtensions.PluginManager": { 4 | "commandName": "Executable", 5 | "executablePath": "$(GitExtensionsExecutablePath)" 6 | } 7 | } 8 | } -------------------------------------------------------------------------------- /src/GitExtensions.PluginManager/Resources/box-search-result.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gitextensions/gitextensions.pluginmanager/daaf7af3ab2a895afc5dab4e494c585455a39924/src/GitExtensions.PluginManager/Resources/box-search-result.png -------------------------------------------------------------------------------- /src/PackageManager.Cli/AllPackageSourceSelector.cs: -------------------------------------------------------------------------------- 1 | using Neptuo; 2 | using PackageManager.Models; 3 | using PackageManager.ViewModels; 4 | using System.Collections.Generic; 5 | 6 | namespace PackageManager 7 | { 8 | public class AllPackageSourceSelector : IPackageSourceSelector 9 | { 10 | private readonly IPackageSourceProvider service; 11 | 12 | public IEnumerable Sources => service.All; 13 | 14 | public AllPackageSourceSelector(IPackageSourceProvider service) 15 | { 16 | Ensure.NotNull(service, "service"); 17 | this.service = service; 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/PackageManager.Cli/PackageManager.Cli.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Exe 5 | PackageManager 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /src/PackageManager.Cli/SelfUpdateService.IApplication.cs: -------------------------------------------------------------------------------- 1 | namespace PackageManager.Services 2 | { 3 | internal partial class SelfUpdateService 4 | { 5 | public interface IApplication 6 | { 7 | IArgs Args { get; } 8 | void Shutdown(); 9 | } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/PackageManager.Cli/SelfUpdateService.IArgs.cs: -------------------------------------------------------------------------------- 1 | using Neptuo; 2 | 3 | namespace PackageManager.Services 4 | { 5 | internal partial class SelfUpdateService 6 | { 7 | public interface IArgs : ICloneable 8 | { 9 | string Path { get; } 10 | 11 | bool IsSelfUpdate { get; set; } 12 | string SelfOriginalPath { get; set; } 13 | string SelfUpdateVersion { get; set; } 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/PackageManager.NuGet/Logging/NuGetLogger.cs: -------------------------------------------------------------------------------- 1 | using Neptuo; 2 | using Neptuo.Logging; 3 | using NuGet.Common; 4 | using System.Threading.Tasks; 5 | using LogLevel = Neptuo.Logging.LogLevel; 6 | using NuGetLogLevel = NuGet.Common.LogLevel; 7 | 8 | namespace PackageManager.Logging 9 | { 10 | public class NuGetLogger : ILogger 11 | { 12 | private readonly ILog log; 13 | 14 | public NuGetLogger(ILog log) 15 | { 16 | Ensure.NotNull(log, "log"); 17 | this.log = log; 18 | } 19 | 20 | private LogLevel MapLevel(NuGetLogLevel level) 21 | { 22 | switch (level) 23 | { 24 | case NuGetLogLevel.Debug: 25 | return LogLevel.Debug; 26 | case NuGetLogLevel.Verbose: 27 | return LogLevel.Debug; 28 | case NuGetLogLevel.Information: 29 | return LogLevel.Info; 30 | case NuGetLogLevel.Minimal: 31 | return LogLevel.Info; 32 | case NuGetLogLevel.Warning: 33 | return LogLevel.Warning; 34 | case NuGetLogLevel.Error: 35 | return LogLevel.Error; 36 | default: 37 | throw Ensure.Exception.NotSupported(level); 38 | } 39 | } 40 | 41 | public void Log(NuGetLogLevel level, string data) 42 | { 43 | log.Log(MapLevel(level), data); 44 | } 45 | 46 | public void Log(ILogMessage message) 47 | { 48 | log.Log(MapLevel(message.Level), message.Message); 49 | } 50 | 51 | public Task LogAsync(NuGetLogLevel level, string data) 52 | { 53 | Log(level, data); 54 | return Task.CompletedTask; 55 | } 56 | 57 | public Task LogAsync(ILogMessage message) 58 | { 59 | Log(message); 60 | return Task.CompletedTask; 61 | } 62 | 63 | public void LogDebug(string data) => Log(NuGetLogLevel.Debug, data); 64 | public void LogError(string data) => Log(NuGetLogLevel.Error, data); 65 | public void LogInformation(string data) => Log(NuGetLogLevel.Information, data); 66 | public void LogInformationSummary(string data) => Log(NuGetLogLevel.Information, data); 67 | public void LogMinimal(string data) => Log(NuGetLogLevel.Minimal, data); 68 | public void LogVerbose(string data) => Log(NuGetLogLevel.Verbose, data); 69 | public void LogWarning(string data) => Log(NuGetLogLevel.Warning, data); 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /src/PackageManager.NuGet/Models/InvalidPackageSourceImplementationException.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace PackageManager.Models 4 | { 5 | /// 6 | /// Raised when passed implementation of to not compatible with , 7 | /// 8 | public class InvalidPackageSourceImplementationException : Exception 9 | { 10 | /// 11 | /// Creates a new empty instance. 12 | /// 13 | public InvalidPackageSourceImplementationException() 14 | { } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/PackageManager.NuGet/Models/NuGetInstalledPackage.cs: -------------------------------------------------------------------------------- 1 | using Neptuo; 2 | 3 | namespace PackageManager.Models 4 | { 5 | public class NuGetInstalledPackage : IInstalledPackage 6 | { 7 | public IPackage Definition { get; } 8 | public bool IsCompatible { get; } 9 | 10 | public NuGetInstalledPackage(IPackage definition, bool isCompatible) 11 | { 12 | Ensure.NotNull(definition, "definition"); 13 | Definition = definition; 14 | IsCompatible = isCompatible; 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/PackageManager.NuGet/Models/NuGetPackage.cs: -------------------------------------------------------------------------------- 1 | using Neptuo; 2 | using NuGet.Protocol.Core.Types; 3 | using PackageManager.Services; 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Threading; 7 | using System.Threading.Tasks; 8 | 9 | namespace PackageManager.Models 10 | { 11 | public class NuGetPackage : NuGetPackageIdentity, IPackage 12 | { 13 | private readonly IPackageSearchMetadata source; 14 | private readonly SourceRepository repository; 15 | private readonly NuGetPackageContentService contentService; 16 | private readonly NuGetPackageVersionService versionService; 17 | 18 | public string Description => source.Description; 19 | 20 | public string Authors => source.Authors; 21 | public DateTime? Published => source.Published?.DateTime; 22 | public string Tags => source.Tags; 23 | 24 | public Uri IconUrl => source.IconUrl; 25 | public Uri ProjectUrl => source.ProjectUrl; 26 | public Uri LicenseUrl => source.LicenseUrl; 27 | 28 | public NuGetPackage(IPackageSearchMetadata source, SourceRepository repository, NuGetPackageContentService contentService, NuGetPackageVersionService versionService) 29 | : base(source?.Identity) 30 | { 31 | Ensure.NotNull(source, "source"); 32 | Ensure.NotNull(repository, "repository"); 33 | Ensure.NotNull(contentService, "contentService"); 34 | Ensure.NotNull(versionService, "versionService"); 35 | this.source = source; 36 | this.repository = repository; 37 | this.contentService = contentService; 38 | this.versionService = versionService; 39 | } 40 | 41 | public async Task GetContentAsync(CancellationToken cancellationToken) 42 | => await contentService.DownloadAsync(repository, source, cancellationToken); 43 | 44 | public async Task> GetVersionsAsync(bool isPrereleaseIncluded, CancellationToken cancellationToken) 45 | => await versionService.GetListAsync(int.MaxValue, source, repository, isPrereleaseIncluded: isPrereleaseIncluded, cancellationToken: cancellationToken); 46 | 47 | public bool Equals(IPackage other) 48 | => Equals((IPackageIdentity)other); 49 | 50 | public override bool Equals(object obj) 51 | { 52 | if (obj is IPackage other) 53 | return Equals(other); 54 | 55 | return false; 56 | } 57 | 58 | public override int GetHashCode() 59 | { 60 | int hash = 17 * 2; 61 | hash += 5 * Id.GetHashCode(); 62 | hash += 5 * Version.GetHashCode(); 63 | return hash; 64 | } 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /src/PackageManager.NuGet/Models/NuGetPackageContent.AnyFrameworkFilter.cs: -------------------------------------------------------------------------------- 1 | using NuGet.Packaging; 2 | 3 | namespace PackageManager.Models 4 | { 5 | partial class NuGetPackageContent 6 | { 7 | public class AnyFrameworkFilter : IFrameworkFilter 8 | { 9 | public bool IsPassed(FrameworkSpecificGroup group) 10 | => group.TargetFramework.IsAny; 11 | 12 | private static AnyFrameworkFilter instance; 13 | private static object instanceLock = new object(); 14 | 15 | public static AnyFrameworkFilter Instance 16 | { 17 | get 18 | { 19 | if (instance == null) 20 | { 21 | lock (instanceLock) 22 | { 23 | if (instance == null) 24 | instance = new AnyFrameworkFilter(); 25 | } 26 | } 27 | 28 | return instance; 29 | } 30 | } 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/PackageManager.NuGet/Models/NuGetPackageContent.IFrameworkFilter.cs: -------------------------------------------------------------------------------- 1 | using NuGet.Packaging; 2 | 3 | namespace PackageManager.Models 4 | { 5 | partial class NuGetPackageContent 6 | { 7 | public interface IFrameworkFilter 8 | { 9 | bool IsPassed(FrameworkSpecificGroup group); 10 | } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/PackageManager.NuGet/Models/NuGetPackageIdentity.cs: -------------------------------------------------------------------------------- 1 | using Neptuo; 2 | using NuGet.Packaging.Core; 3 | using System; 4 | 5 | namespace PackageManager.Models 6 | { 7 | public class NuGetPackageIdentity : IPackageIdentity 8 | { 9 | private readonly PackageIdentity identity; 10 | 11 | public string Id => identity.Id; 12 | public string Version => identity.Version.ToFullString(); 13 | 14 | public NuGetPackageIdentity(PackageIdentity identity) 15 | { 16 | Ensure.NotNull(identity, "identity"); 17 | this.identity = identity; 18 | } 19 | 20 | public bool Equals(IPackageIdentity other) 21 | { 22 | if (other == null) 23 | return false; 24 | 25 | return string.Equals(Id, other.Id, StringComparison.CurrentCultureIgnoreCase) && string.Equals(Version, other.Version, StringComparison.CurrentCultureIgnoreCase); 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/PackageManager.NuGet/Models/NuGetPackageSource.cs: -------------------------------------------------------------------------------- 1 | using Neptuo; 2 | using NuGet.Configuration; 3 | using System; 4 | 5 | namespace PackageManager.Models 6 | { 7 | public class NuGetPackageSource : IPackageSource 8 | { 9 | internal PackageSource Original { get; } 10 | 11 | public string Name => Original.Name; 12 | public Uri Uri => Original.SourceUri; 13 | 14 | public NuGetPackageSource(PackageSource source) 15 | { 16 | Ensure.NotNull(source, "source"); 17 | Original = source; 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/PackageManager.NuGet/Models/NuGetPackageSourceBuilder.cs: -------------------------------------------------------------------------------- 1 | using NuGet.Configuration; 2 | using System; 3 | 4 | namespace PackageManager.Models 5 | { 6 | public class NuGetPackageSourceBuilder : IPackageSourceBuilder 7 | { 8 | private readonly NuGetPackageSourceCollection service; 9 | private readonly NuGetPackageSource edit; 10 | 11 | private string name; 12 | private Uri uri; 13 | 14 | internal NuGetPackageSourceBuilder(NuGetPackageSourceCollection service) 15 | { 16 | this.service = service; 17 | } 18 | 19 | internal NuGetPackageSourceBuilder(NuGetPackageSourceCollection service, NuGetPackageSource edit) 20 | { 21 | this.service = service; 22 | this.edit = edit; 23 | this.name = edit.Name; 24 | this.uri = edit.Uri; 25 | } 26 | 27 | public IPackageSourceBuilder Name(string name) 28 | { 29 | this.name = name; 30 | return this; 31 | } 32 | 33 | public IPackageSourceBuilder Uri(Uri uri) 34 | { 35 | this.uri = uri; 36 | return this; 37 | } 38 | 39 | public IPackageSource Save() 40 | { 41 | if (edit == null) 42 | { 43 | var source = new NuGetPackageSource(new PackageSource(uri.ToString(), name)); 44 | service.Sources.Add(source); 45 | service.SavePackageSources(); 46 | return source; 47 | } 48 | else if(edit.Name == name) 49 | { 50 | edit.Original.Source = uri.ToString(); 51 | service.SavePackageSources(); 52 | return edit; 53 | } 54 | else 55 | { 56 | int index = service.Sources.IndexOf(edit); 57 | service.Sources.Remove(edit); 58 | 59 | var source = new NuGetPackageSource(new PackageSource(uri.ToString(), name)); 60 | service.Sources.Insert(index, source); 61 | service.SavePackageSources(); 62 | return source; 63 | } 64 | } 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /src/PackageManager.NuGet/Models/NuGetPackageVersionComparer.cs: -------------------------------------------------------------------------------- 1 | using NuGet.Versioning; 2 | using System.Collections.Generic; 3 | 4 | namespace PackageManager.Models 5 | { 6 | public class NuGetPackageVersionComparer : IComparer 7 | { 8 | public static readonly NuGetPackageVersionComparer Instance = new NuGetPackageVersionComparer(); 9 | 10 | public int Compare(IPackageIdentity x, IPackageIdentity y) 11 | { 12 | NuGetVersion xVersion = new NuGetVersion(x.Version); 13 | NuGetVersion yVersion = new NuGetVersion(y.Version); 14 | return xVersion.CompareTo(yVersion); 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/PackageManager.NuGet/PackageManager.NuGet.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | PackageManager 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /src/PackageManager.NuGet/Services/EmptyNuGetSearchTermTransformer.cs: -------------------------------------------------------------------------------- 1 | namespace PackageManager.Services 2 | { 3 | public class EmptyNuGetSearchTermTransformer : INuGetSearchTermTransformer 4 | { 5 | public void Transform(NuGetSearchTerm searchTerm) 6 | { 7 | } 8 | 9 | public readonly static EmptyNuGetSearchTermTransformer Instance = new EmptyNuGetSearchTermTransformer(); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/PackageManager.NuGet/Services/INuGetPackageFilter.cs: -------------------------------------------------------------------------------- 1 | using NuGet.Protocol.Core.Types; 2 | using System.Threading; 3 | using System.Threading.Tasks; 4 | 5 | namespace PackageManager.Services 6 | { 7 | public interface INuGetPackageFilter 8 | { 9 | Task FilterAsync(SourceRepository repository, IPackageSearchMetadata package, CancellationToken cancellationToken); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/PackageManager.NuGet/Services/INuGetSearchTermTransformer.cs: -------------------------------------------------------------------------------- 1 | namespace PackageManager.Services 2 | { 3 | public interface INuGetSearchTermTransformer 4 | { 5 | void Transform(NuGetSearchTerm searchTerm); 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /src/PackageManager.NuGet/Services/NuGetPackageContentService.cs: -------------------------------------------------------------------------------- 1 | using Neptuo; 2 | using Neptuo.Logging; 3 | using NuGet.Common; 4 | using NuGet.Packaging; 5 | using NuGet.Protocol.Core.Types; 6 | using PackageManager.Logging; 7 | using PackageManager.Models; 8 | using System; 9 | using System.IO; 10 | using System.Threading; 11 | using System.Threading.Tasks; 12 | 13 | namespace PackageManager.Services 14 | { 15 | public class NuGetPackageContentService 16 | { 17 | private readonly ILog log; 18 | private readonly ILogger nuGetLog; 19 | private readonly NuGetPackageContent.IFrameworkFilter frameworkFilter; 20 | 21 | public NuGetPackageContentService(ILog log, NuGetPackageContent.IFrameworkFilter frameworkFilter = null) 22 | { 23 | Ensure.NotNull(log, "log"); 24 | this.log = log.Factory.Scope("Package"); 25 | this.nuGetLog = new NuGetLogger(this.log); 26 | this.frameworkFilter = frameworkFilter; 27 | } 28 | 29 | public async Task DownloadAsync(SourceRepository repository, IPackageSearchMetadata package, CancellationToken cancellationToken) 30 | { 31 | Ensure.NotNull(repository, "repository"); 32 | Ensure.NotNull(package, "package"); 33 | 34 | DownloadResource download = await repository.GetResourceAsync(); 35 | if (download == null) 36 | throw Ensure.Exception.InvalidOperation($"Unnable to resolve '{nameof(DownloadResource)}'."); 37 | 38 | using (var sourceCacheContext = new SourceCacheContext()) 39 | { 40 | var context = new PackageDownloadContext(sourceCacheContext, Path.GetTempPath(), true); 41 | var result = await download.GetDownloadResourceResultAsync(package.Identity, context, string.Empty, nuGetLog, cancellationToken); 42 | if (result.Status == DownloadResourceResultStatus.Cancelled) 43 | throw new OperationCanceledException(); 44 | else if (result.Status == DownloadResourceResultStatus.NotFound) 45 | throw Ensure.Exception.InvalidOperation($"Package '{package.Identity.Id}-v{package.Identity.Version}' not found"); 46 | 47 | return new NuGetPackageContent(new PackageArchiveReader(result.PackageStream), log, frameworkFilter); 48 | } 49 | } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/PackageManager.NuGet/Services/NuGetPackageFilterResult.cs: -------------------------------------------------------------------------------- 1 | namespace PackageManager.Services 2 | { 3 | public enum NuGetPackageFilterResult 4 | { 5 | Ok, 6 | NotCompatible, 7 | NotCompatibleVersion 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /src/PackageManager.NuGet/Services/NuGetSourceRepositoryFactory.cs: -------------------------------------------------------------------------------- 1 | using Neptuo; 2 | using Neptuo.Activators; 3 | using NuGet.Protocol.Core.Types; 4 | using PackageManager.Models; 5 | 6 | namespace PackageManager.Services 7 | { 8 | public class NuGetSourceRepositoryFactory : IFactory 9 | { 10 | public SourceRepository Create(IPackageSource packageSource) 11 | { 12 | Ensure.NotNull(packageSource, "packageSource"); 13 | 14 | if (packageSource is NuGetPackageSource nuget) 15 | return Repository.CreateSource(Repository.Provider.GetCoreV3(), nuget.Original); 16 | 17 | return Repository.CreateSource(Repository.Provider.GetCoreV3(), packageSource.Uri.ToString()); 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/PackageManager.NuGet/Services/OkNuGetPackageFilter.cs: -------------------------------------------------------------------------------- 1 | using System.Threading; 2 | using System.Threading.Tasks; 3 | using NuGet.Protocol.Core.Types; 4 | 5 | namespace PackageManager.Services 6 | { 7 | public class OkNuGetPackageFilter : INuGetPackageFilter 8 | { 9 | public Task FilterAsync(SourceRepository repository, IPackageSearchMetadata package, CancellationToken cancellationToken) 10 | => Task.FromResult(NuGetPackageFilterResult.Ok); 11 | 12 | public readonly static OkNuGetPackageFilter Instance = new OkNuGetPackageFilter(); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/PackageManager.UI/Args.Partial.cs: -------------------------------------------------------------------------------- 1 | using Neptuo; 2 | using PackageManager.Services; 3 | 4 | namespace PackageManager 5 | { 6 | partial class Args : SelfUpdateService.IArgs, ICloneable 7 | { 8 | SelfUpdateService.IArgs ICloneable.Clone() 9 | => Clone(); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/PackageManager.UI/Exceptions/MessageExceptionHandler.cs: -------------------------------------------------------------------------------- 1 | using Neptuo; 2 | using Neptuo.Exceptions.Handlers; 3 | using PackageManager.Services; 4 | using System; 5 | using System.Text; 6 | 7 | namespace PackageManager.Exceptions 8 | { 9 | internal class MessageExceptionHandler : IExceptionHandler> 10 | { 11 | private readonly Navigator navigator; 12 | 13 | public MessageExceptionHandler(Navigator navigator) 14 | { 15 | Ensure.NotNull(navigator, "navigator"); 16 | this.navigator = navigator; 17 | } 18 | 19 | public void Handle(IExceptionHandlerContext context) 20 | { 21 | StringBuilder message = new StringBuilder(); 22 | 23 | string exceptionMessage = context.Exception.ToString(); 24 | if (exceptionMessage.Length > 800) 25 | exceptionMessage = exceptionMessage.Substring(0, 800); 26 | 27 | message.AppendLine(exceptionMessage); 28 | 29 | bool result = navigator.Confirm("Unhandled exception - Do you want to kill the aplication?", message.ToString(), Navigator.MessageType.Error); 30 | if (!result) 31 | context.IsHandled = true; 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/PackageManager.UI/Exceptions/NuGetFatalProtocolExceptionHandler.cs: -------------------------------------------------------------------------------- 1 | using Neptuo; 2 | using Neptuo.Exceptions.Handlers; 3 | using NuGet.Protocol.Core.Types; 4 | using PackageManager.Services; 5 | using System.Net; 6 | using System.Net.Http; 7 | 8 | namespace PackageManager.Exceptions 9 | { 10 | internal class NuGetFatalProtocolExceptionHandler : IExceptionHandler> 11 | { 12 | private readonly Navigator navigator; 13 | 14 | public NuGetFatalProtocolExceptionHandler(Navigator navigator) 15 | { 16 | Ensure.NotNull(navigator, "navigator"); 17 | this.navigator = navigator; 18 | } 19 | 20 | void IExceptionHandler>.Handle(IExceptionHandlerContext context) 21 | { 22 | if (context.Exception.InnerException is HttpRequestException && context.Exception.InnerException.InnerException is WebException webException) 23 | { 24 | navigator.Notify("Communcation Error", GetMessage(webException), Navigator.MessageType.Error); 25 | context.IsHandled = true; 26 | } 27 | } 28 | 29 | private string GetMessage(WebException exception) 30 | { 31 | switch (exception.Status) 32 | { 33 | case WebExceptionStatus.NameResolutionFailure: 34 | return "Error resolving the host name."; 35 | case WebExceptionStatus.ConnectFailure: 36 | return "Error opening the connection to the server."; 37 | case WebExceptionStatus.ReceiveFailure: 38 | return "Error receiving data over the connection."; 39 | case WebExceptionStatus.RequestCanceled: 40 | return "Request has been canceled."; 41 | case WebExceptionStatus.ConnectionClosed: 42 | return "The connection has been unexpectedly closed."; 43 | case WebExceptionStatus.Timeout: 44 | return "The connection has timed out."; 45 | case WebExceptionStatus.ProxyNameResolutionFailure: 46 | return "Error resolving proxy name."; 47 | case WebExceptionStatus.Success: 48 | case WebExceptionStatus.SendFailure: 49 | case WebExceptionStatus.PipelineFailure: 50 | case WebExceptionStatus.ProtocolError: 51 | case WebExceptionStatus.TrustFailure: 52 | case WebExceptionStatus.SecureChannelFailure: 53 | case WebExceptionStatus.ServerProtocolViolation: 54 | case WebExceptionStatus.KeepAliveFailure: 55 | case WebExceptionStatus.Pending: 56 | case WebExceptionStatus.UnknownError: 57 | case WebExceptionStatus.MessageLengthLimitExceeded: 58 | case WebExceptionStatus.CacheEntryNotFound: 59 | case WebExceptionStatus.RequestProhibitedByCachePolicy: 60 | case WebExceptionStatus.RequestProhibitedByProxy: 61 | default: 62 | return "An unknown error has occured while communicating over the wire."; 63 | } 64 | } 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /src/PackageManager.UI/Exceptions/PackageInstallExceptionHandler.cs: -------------------------------------------------------------------------------- 1 | using Neptuo; 2 | using Neptuo.Exceptions.Handlers; 3 | using PackageManager.Models; 4 | using PackageManager.Services; 5 | 6 | namespace PackageManager.Exceptions 7 | { 8 | internal class PackageInstallExceptionHandler : 9 | IExceptionHandler>, 10 | IExceptionHandler> 11 | { 12 | private readonly Navigator navigator; 13 | 14 | public PackageInstallExceptionHandler(Navigator navigator) 15 | { 16 | Ensure.NotNull(navigator, "navigator"); 17 | this.navigator = navigator; 18 | } 19 | 20 | void IExceptionHandler>.Handle(IExceptionHandlerContext context) 21 | { 22 | navigator.Notify("Package Install Error", $"Error extracting file to '{context.Exception.FilePath}'", Navigator.MessageType.Error); 23 | context.IsHandled = true; 24 | } 25 | 26 | void IExceptionHandler>.Handle(IExceptionHandlerContext context) 27 | { 28 | navigator.Notify("Package Removal Error", $"Error deleting file '{context.Exception.FilePath}'", Navigator.MessageType.Error); 29 | context.IsHandled = true; 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/PackageManager.UI/Exceptions/RestartAsAdministratorCancelledExceptionHandler.cs: -------------------------------------------------------------------------------- 1 | using Neptuo; 2 | using Neptuo.Exceptions.Handlers; 3 | using PackageManager.Services; 4 | 5 | namespace PackageManager.Exceptions 6 | { 7 | public class RestartAsAdministratorCancelledExceptionHandler : IExceptionHandler> 8 | { 9 | private readonly Navigator navigator; 10 | private readonly App application; 11 | 12 | internal RestartAsAdministratorCancelledExceptionHandler(Navigator navigator, App application) 13 | { 14 | Ensure.NotNull(navigator, "navigator"); 15 | Ensure.NotNull(application, "application"); 16 | this.navigator = navigator; 17 | this.application = application; 18 | } 19 | 20 | public void Handle(IExceptionHandlerContext context) 21 | { 22 | context.IsHandled = true; 23 | 24 | navigator.Notify("Unauthorized", "The operation requires elevated privilege which has not been given.", Navigator.MessageType.Error); 25 | application.Shutdown(); 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/PackageManager.UI/Exceptions/ShutdownExceptionHandler.cs: -------------------------------------------------------------------------------- 1 | using Neptuo; 2 | using Neptuo.Exceptions.Handlers; 3 | using System; 4 | 5 | namespace PackageManager.Exceptions 6 | { 7 | internal class ShutdownExceptionHandler : IExceptionHandler 8 | { 9 | private readonly App application; 10 | 11 | public ShutdownExceptionHandler(App application) 12 | { 13 | Ensure.NotNull(application, "application"); 14 | this.application = application; 15 | } 16 | 17 | void IExceptionHandler.Handle(Exception exception) => application.Shutdown(); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/PackageManager.UI/Exceptions/UnauthorizedExceptionHandler.cs: -------------------------------------------------------------------------------- 1 | using Neptuo; 2 | using Neptuo.Exceptions.Handlers; 3 | using NuGet.Configuration; 4 | using NuGet.Packaging; 5 | using PackageManager.Services; 6 | using System; 7 | 8 | namespace PackageManager.Exceptions 9 | { 10 | internal class UnauthorizedExceptionHandler : 11 | IExceptionHandler>, 12 | IExceptionHandler>, 13 | IExceptionHandler> 14 | { 15 | private readonly ProcessService processService; 16 | 17 | public UnauthorizedExceptionHandler(ProcessService processService) 18 | { 19 | Ensure.NotNull(processService, "processService"); 20 | this.processService = processService; 21 | } 22 | 23 | private void HandleInternal(IExceptionHandlerContext context) 24 | where T : Exception 25 | { 26 | processService.RestartAsAdministrator(); 27 | context.IsHandled = true; 28 | } 29 | 30 | void IExceptionHandler>.Handle(IExceptionHandlerContext context) => HandleInternal(context); 31 | void IExceptionHandler>.Handle(IExceptionHandlerContext context) => HandleInternal(context); 32 | void IExceptionHandler>.Handle(IExceptionHandlerContext context) => HandleInternal(context); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/PackageManager.UI/Logging/Serialization/MemoryLogSerializer.cs: -------------------------------------------------------------------------------- 1 | using System.Text; 2 | using Neptuo; 3 | using Neptuo.Logging; 4 | using Neptuo.Logging.Serialization; 5 | using Neptuo.Logging.Serialization.Formatters; 6 | 7 | namespace PackageManager.Logging.Serialization 8 | { 9 | public class MemoryLogSerializer : ILogSerializer 10 | { 11 | private readonly StringBuilder content = new StringBuilder(); 12 | private readonly ILogFormatter formatter; 13 | 14 | public MemoryLogSerializer(ILogFormatter formatter) 15 | { 16 | Ensure.NotNull(formatter, "formatter"); 17 | this.formatter = formatter; 18 | } 19 | 20 | public string GetContent() 21 | => content.ToString(); 22 | 23 | public void Clear() 24 | => content.Clear(); 25 | 26 | public void Append(string scopeName, LogLevel level, object model) 27 | => content.AppendLine(formatter.Format(scopeName, level, model)); 28 | 29 | public bool IsEnabled(string scopeName, LogLevel level) 30 | => true; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/PackageManager.UI/Models/NuGetFrameworkFilter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using NuGet.Frameworks; 5 | using NuGet.Packaging; 6 | 7 | namespace PackageManager.Models 8 | { 9 | internal class NuGetFrameworkFilter : NuGetPackageContent.IFrameworkFilter 10 | { 11 | private readonly IReadOnlyCollection collection; 12 | 13 | public NuGetFrameworkFilter(IReadOnlyCollection collection) 14 | => this.collection = collection; 15 | 16 | public bool IsPassed(FrameworkSpecificGroup group) 17 | => collection.Contains(group.TargetFramework); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/PackageManager.UI/Models/SelfPackage.cs: -------------------------------------------------------------------------------- 1 | using Neptuo; 2 | using System; 3 | 4 | namespace PackageManager.Models 5 | { 6 | internal class SelfPackage : IPackageIdentity 7 | { 8 | public string Id { get; } 9 | public string Version { get; } 10 | 11 | public SelfPackage(string id) 12 | { 13 | Ensure.NotNull(id, "id"); 14 | Id = id; 15 | Version = VersionInfo.Version; 16 | 17 | int indexOfPlus = Version.IndexOf('+'); 18 | if (indexOfPlus > 0) 19 | Version = Version.Substring(0, indexOfPlus); 20 | } 21 | 22 | public bool Equals(IPackageIdentity other) 23 | { 24 | if (other == null) 25 | return false; 26 | 27 | return string.Equals(Id, other.Id, StringComparison.CurrentCultureIgnoreCase) && string.Equals(Version, other.Version, StringComparison.CurrentCultureIgnoreCase); 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/PackageManager.UI/PackageManager.UI.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | WinExe 5 | true 6 | PackageManager 7 | PackageManager.UI 8 | Views\Assets\box-search-result.ico 9 | PackageManager.Program 10 | 11 | true 12 | false 13 | $(PackageManagerUIRuntimeIdentifier) 14 | true 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | True 34 | True 35 | Resources.resx 36 | 37 | 38 | True 39 | True 40 | Settings.settings 41 | 42 | 43 | 44 | 45 | 46 | ResXFileCodeGenerator 47 | Resources.Designer.cs 48 | 49 | 50 | 51 | 52 | 53 | SettingsSingleFileGenerator 54 | Settings.Designer.cs 55 | 56 | 57 | -------------------------------------------------------------------------------- /src/PackageManager.UI/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Threading; 3 | using System.Diagnostics; 4 | using System.Linq; 5 | using System.Runtime.InteropServices; 6 | 7 | namespace PackageManager 8 | { 9 | public static class Program 10 | { 11 | private const string ApplicationKey = "5CFB158B-8346-4588-926D-99006A5195B6"; 12 | private const int RestoreWindowCommandCode = 0x09; 13 | 14 | [DllImport("user32.dll")] 15 | [return: MarshalAs(UnmanagedType.Bool)] 16 | private static extern bool ShowWindow(IntPtr hWnd, int nCmdShow); 17 | 18 | [DllImport("user32.dll")] 19 | private static extern IntPtr SetForegroundWindow(IntPtr hWnd); 20 | 21 | [STAThread] 22 | public static void Main() 23 | { 24 | using var mutex = new Mutex(false, ApplicationKey, out bool createdNew); 25 | 26 | if (createdNew) 27 | { 28 | var application = new App(); 29 | 30 | application.InitializeComponent(); 31 | application.Run(); 32 | } 33 | else 34 | { 35 | var currentProcess = Process.GetCurrentProcess(); 36 | var mainProcess = Process.GetProcesses() 37 | .Where(x => x.Id != currentProcess.Id) 38 | .FirstOrDefault(x => x.ProcessName == currentProcess.ProcessName); 39 | 40 | if (mainProcess != null) 41 | { 42 | ShowWindow(mainProcess.MainWindowHandle, RestoreWindowCommandCode); 43 | SetForegroundWindow(mainProcess.MainWindowHandle); 44 | } 45 | } 46 | } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/PackageManager.UI/Properties/Resources.Designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // Runtime Version:4.0.30319.42000 5 | // 6 | // Changes to this file may cause incorrect behavior and will be lost if 7 | // the code is regenerated. 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | namespace PackageManager.Properties { 12 | using System; 13 | 14 | 15 | /// 16 | /// A strongly-typed resource class, for looking up localized strings, etc. 17 | /// 18 | // This class was auto-generated by the StronglyTypedResourceBuilder 19 | // class via a tool like ResGen or Visual Studio. 20 | // To add or remove a member, edit your .ResX file then rerun ResGen 21 | // with the /str option, or rebuild your VS project. 22 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "15.0.0.0")] 23 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 24 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] 25 | internal class Resources { 26 | 27 | private static global::System.Resources.ResourceManager resourceMan; 28 | 29 | private static global::System.Globalization.CultureInfo resourceCulture; 30 | 31 | [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] 32 | internal Resources() { 33 | } 34 | 35 | /// 36 | /// Returns the cached ResourceManager instance used by this class. 37 | /// 38 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] 39 | internal static global::System.Resources.ResourceManager ResourceManager { 40 | get { 41 | if (object.ReferenceEquals(resourceMan, null)) { 42 | global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("PackageManager.Properties.Resources", typeof(Resources).Assembly); 43 | resourceMan = temp; 44 | } 45 | return resourceMan; 46 | } 47 | } 48 | 49 | /// 50 | /// Overrides the current thread's CurrentUICulture property for all 51 | /// resource lookups using this strongly typed resource class. 52 | /// 53 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] 54 | internal static global::System.Globalization.CultureInfo Culture { 55 | get { 56 | return resourceCulture; 57 | } 58 | set { 59 | resourceCulture = value; 60 | } 61 | } 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /src/PackageManager.UI/Properties/Settings.Designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // Runtime Version:4.0.30319.42000 5 | // 6 | // Changes to this file may cause incorrect behavior and will be lost if 7 | // the code is regenerated. 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | namespace PackageManager.Properties { 12 | 13 | 14 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] 15 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "15.9.0.0")] 16 | internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { 17 | 18 | private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); 19 | 20 | public static Settings Default { 21 | get { 22 | return defaultInstance; 23 | } 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/PackageManager.UI/Properties/Settings.settings: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /src/PackageManager.UI/Properties/VersionInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | 3 | namespace PackageManager 4 | { 5 | public static class VersionInfo 6 | { 7 | public static string Version => typeof(VersionInfo).Assembly.GetCustomAttribute().InformationalVersion; 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /src/PackageManager.UI/Services/ProcessService.IApplication.cs: -------------------------------------------------------------------------------- 1 | namespace PackageManager.Services 2 | { 3 | partial class ProcessService 4 | { 5 | public interface IApplication 6 | { 7 | object Args { get; } 8 | 9 | void Shutdown(); 10 | } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/PackageManager.UI/Services/ProcessService.ProcessKillContext.cs: -------------------------------------------------------------------------------- 1 | using Neptuo; 2 | using System.Collections.Generic; 3 | using System.ComponentModel; 4 | using System.Diagnostics; 5 | using System.Linq; 6 | 7 | namespace PackageManager.Services 8 | { 9 | partial class ProcessService 10 | { 11 | internal class ProcessKillContext 12 | { 13 | private readonly IReadOnlyCollection targets; 14 | 15 | public ProcessKillContext(IReadOnlyCollection names) 16 | { 17 | Ensure.NotNull(names, "names"); 18 | ProcessNames = names; 19 | targets = names.SelectMany(name => Process.GetProcessesByName(name)).ToList(); 20 | } 21 | 22 | public IReadOnlyCollection ProcessNames { get; } 23 | 24 | public int ProcessCount { get => targets.Count; } 25 | 26 | public bool IsExecutable => targets.Count > 0; 27 | 28 | public void Execute() 29 | { 30 | foreach (Process process in targets) 31 | { 32 | try 33 | { 34 | process.Kill(); 35 | } 36 | catch (Win32Exception) 37 | { 38 | continue; 39 | } 40 | } 41 | } 42 | } 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/PackageManager.UI/Services/ProcessService.cs: -------------------------------------------------------------------------------- 1 | using Neptuo; 2 | using System.Collections.Generic; 3 | using System.ComponentModel; 4 | using System.Diagnostics; 5 | 6 | namespace PackageManager.Services 7 | { 8 | internal partial class ProcessService 9 | { 10 | private const int ErrorCancelled = 1223; 11 | 12 | private readonly IApplication application; 13 | private readonly IReadOnlyCollection toKillNames; 14 | 15 | public ProcessService(IApplication application, IReadOnlyCollection toKillNames) 16 | { 17 | Ensure.NotNull(application, "application"); 18 | Ensure.NotNull(toKillNames, "toKillNames"); 19 | this.application = application; 20 | this.toKillNames = toKillNames; 21 | } 22 | 23 | public void RestartAsAdministrator() 24 | { 25 | Process current = Process.GetCurrentProcess(); 26 | ProcessStartInfo processStart = new ProcessStartInfo( 27 | current.MainModule.FileName, 28 | application.Args.ToString() 29 | ); 30 | 31 | processStart.Verb = "runas"; 32 | 33 | try 34 | { 35 | Process.Start(processStart); 36 | } 37 | catch (Win32Exception e) when (e.NativeErrorCode == ErrorCancelled) 38 | { 39 | throw new RestartAsAdministratorCancelledException(e); 40 | } 41 | 42 | application.Shutdown(); 43 | } 44 | 45 | public void Run(string filePath, string arguments) 46 | { 47 | ProcessStartInfo processStart = new ProcessStartInfo( 48 | filePath, 49 | arguments 50 | ); 51 | 52 | Process.Start(processStart); 53 | } 54 | 55 | public ProcessKillContext PrepareContextForProcessesKillBeforeChange() 56 | => new ProcessKillContext(toKillNames); 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/PackageManager.UI/Services/RestartAsAdministratorCancelledException.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace PackageManager.Services 4 | { 5 | /// 6 | /// An exception raised when attempt to restart the application as administrator was cancelled by the user. 7 | /// 8 | public class RestartAsAdministratorCancelledException : Exception 9 | { 10 | /// 11 | /// Creates new instance with the exception. 12 | /// 13 | /// The inner cause of the exceptional state. 14 | public RestartAsAdministratorCancelledException(Exception inner) 15 | : base("Attempt to restart the application as administrator was cancelled by the user.", inner) 16 | { } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/PackageManager.UI/Services/SelfUpdateService.IApplication.cs: -------------------------------------------------------------------------------- 1 | namespace PackageManager.Services 2 | { 3 | partial class SelfUpdateService 4 | { 5 | public interface IApplication 6 | { 7 | IArgs Args { get; } 8 | void Shutdown(); 9 | } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/PackageManager.UI/Services/SelfUpdateService.IArgs.cs: -------------------------------------------------------------------------------- 1 | using Neptuo; 2 | 3 | namespace PackageManager.Services 4 | { 5 | partial class SelfUpdateService 6 | { 7 | public interface IArgs : ICloneable 8 | { 9 | string Path { get; } 10 | 11 | bool IsSelfUpdate { get; set; } 12 | string SelfOriginalPath { get; set; } 13 | string SelfUpdateVersion { get; set; } 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/PackageManager.UI/Services/SelfUpdateService.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Diagnostics; 3 | using System.IO; 4 | using System.Linq; 5 | using Neptuo; 6 | using PackageManager.Models; 7 | 8 | namespace PackageManager.Services 9 | { 10 | internal partial class SelfUpdateService : ISelfUpdateService 11 | { 12 | private readonly IApplication application; 13 | private readonly ProcessService processes; 14 | 15 | public SelfUpdateService(IApplication application, ProcessService processes) 16 | { 17 | Ensure.NotNull(application, "application"); 18 | Ensure.NotNull(processes, "processes"); 19 | this.application = application; 20 | this.processes = processes; 21 | } 22 | 23 | public string CurrentFileName => Path.GetFileName(GetCurrentApplicationPath()); 24 | 25 | private static string GetCurrentApplicationPath() => Process.GetCurrentProcess().MainModule!.FileName!; 26 | 27 | public bool IsSelfUpdate => application.Args.IsSelfUpdate; 28 | 29 | public void Update(IPackage latest) 30 | { 31 | string current = GetCurrentApplicationPath(); 32 | string temp = CopySelfToTemp(current); 33 | IArgs arguments = CreateArguments(current, latest); 34 | RerunFromTemp(temp, arguments); 35 | } 36 | 37 | private string CopySelfToTemp(string current) 38 | { 39 | string tempDirectory = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString().Replace("-", string.Empty)); 40 | string temp = Path.Combine(tempDirectory, CurrentFileName); 41 | if (!Directory.Exists(tempDirectory)) 42 | Directory.CreateDirectory(tempDirectory); 43 | 44 | File.Copy(current, temp, true); 45 | return temp; 46 | } 47 | 48 | private void RerunFromTemp(string temp, IArgs arguments) 49 | { 50 | processes.Run(temp, arguments.ToString()); 51 | application.Shutdown(); 52 | } 53 | 54 | private IArgs CreateArguments(string current, IPackageIdentity package) 55 | { 56 | IArgs args = application.Args.Clone(); 57 | 58 | args.IsSelfUpdate = true; 59 | args.SelfOriginalPath = current; 60 | args.SelfUpdateVersion = package.Version; 61 | 62 | return args; 63 | } 64 | 65 | public void RunNewInstance(IPackage package) 66 | { 67 | string target = null; 68 | if (application.Args.SelfOriginalPath != null) 69 | { 70 | target = application.Args.SelfOriginalPath; 71 | } 72 | else 73 | { 74 | target = Directory 75 | .EnumerateFiles(application.Args.Path, CurrentFileName, SearchOption.AllDirectories) 76 | .FirstOrDefault(); 77 | } 78 | 79 | if (target != null) 80 | { 81 | IArgs args = application.Args.Clone(); 82 | 83 | args.IsSelfUpdate = false; 84 | args.SelfUpdateVersion = null; 85 | 86 | string arguments = args.ToString(); 87 | processes.Run(target, arguments); 88 | } 89 | } 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /src/PackageManager.UI/Services/TagsNuGetSearchTermTransformer.cs: -------------------------------------------------------------------------------- 1 | using Neptuo; 2 | 3 | namespace PackageManager.Services 4 | { 5 | public class TagsNuGetSearchTermTransformer : INuGetSearchTermTransformer 6 | { 7 | private readonly string tags; 8 | 9 | public TagsNuGetSearchTermTransformer(string tags) 10 | { 11 | Ensure.NotNull(tags, "tags"); 12 | this.tags = tags; 13 | } 14 | 15 | public void Transform(NuGetSearchTerm searchTerm) 16 | { 17 | if (!string.IsNullOrEmpty(tags)) 18 | searchTerm.Tags.Add(tags); 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/PackageManager.UI/Views/Assets/baseline_add_black_18dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gitextensions/gitextensions.pluginmanager/daaf7af3ab2a895afc5dab4e494c585455a39924/src/PackageManager.UI/Views/Assets/baseline_add_black_18dp.png -------------------------------------------------------------------------------- /src/PackageManager.UI/Views/Assets/baseline_arrow_downward_black_18dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gitextensions/gitextensions.pluginmanager/daaf7af3ab2a895afc5dab4e494c585455a39924/src/PackageManager.UI/Views/Assets/baseline_arrow_downward_black_18dp.png -------------------------------------------------------------------------------- /src/PackageManager.UI/Views/Assets/baseline_arrow_upward_black_18dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gitextensions/gitextensions.pluginmanager/daaf7af3ab2a895afc5dab4e494c585455a39924/src/PackageManager.UI/Views/Assets/baseline_arrow_upward_black_18dp.png -------------------------------------------------------------------------------- /src/PackageManager.UI/Views/Assets/baseline_chevron_left_black_18dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gitextensions/gitextensions.pluginmanager/daaf7af3ab2a895afc5dab4e494c585455a39924/src/PackageManager.UI/Views/Assets/baseline_chevron_left_black_18dp.png -------------------------------------------------------------------------------- /src/PackageManager.UI/Views/Assets/baseline_chevron_right_black_18dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gitextensions/gitextensions.pluginmanager/daaf7af3ab2a895afc5dab4e494c585455a39924/src/PackageManager.UI/Views/Assets/baseline_chevron_right_black_18dp.png -------------------------------------------------------------------------------- /src/PackageManager.UI/Views/Assets/baseline_clear_black_18dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gitextensions/gitextensions.pluginmanager/daaf7af3ab2a895afc5dab4e494c585455a39924/src/PackageManager.UI/Views/Assets/baseline_clear_black_18dp.png -------------------------------------------------------------------------------- /src/PackageManager.UI/Views/Assets/baseline_done_black_18dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gitextensions/gitextensions.pluginmanager/daaf7af3ab2a895afc5dab4e494c585455a39924/src/PackageManager.UI/Views/Assets/baseline_done_black_18dp.png -------------------------------------------------------------------------------- /src/PackageManager.UI/Views/Assets/baseline_edit_black_18dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gitextensions/gitextensions.pluginmanager/daaf7af3ab2a895afc5dab4e494c585455a39924/src/PackageManager.UI/Views/Assets/baseline_edit_black_18dp.png -------------------------------------------------------------------------------- /src/PackageManager.UI/Views/Assets/baseline_refresh_black_18dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gitextensions/gitextensions.pluginmanager/daaf7af3ab2a895afc5dab4e494c585455a39924/src/PackageManager.UI/Views/Assets/baseline_refresh_black_18dp.png -------------------------------------------------------------------------------- /src/PackageManager.UI/Views/Assets/baseline_search_black_18dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gitextensions/gitextensions.pluginmanager/daaf7af3ab2a895afc5dab4e494c585455a39924/src/PackageManager.UI/Views/Assets/baseline_search_black_18dp.png -------------------------------------------------------------------------------- /src/PackageManager.UI/Views/Assets/box-search-result.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gitextensions/gitextensions.pluginmanager/daaf7af3ab2a895afc5dab4e494c585455a39924/src/PackageManager.UI/Views/Assets/box-search-result.ico -------------------------------------------------------------------------------- /src/PackageManager.UI/Views/Assets/box-search-result.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gitextensions/gitextensions.pluginmanager/daaf7af3ab2a895afc5dab4e494c585455a39924/src/PackageManager.UI/Views/Assets/box-search-result.png -------------------------------------------------------------------------------- /src/PackageManager.UI/Views/Assets/default-package-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gitextensions/gitextensions.pluginmanager/daaf7af3ab2a895afc5dab4e494c585455a39924/src/PackageManager.UI/Views/Assets/default-package-icon.png -------------------------------------------------------------------------------- /src/PackageManager.UI/Views/Assets/settings.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gitextensions/gitextensions.pluginmanager/daaf7af3ab2a895afc5dab4e494c585455a39924/src/PackageManager.UI/Views/Assets/settings.png -------------------------------------------------------------------------------- /src/PackageManager.UI/Views/Controls/CompatibilityLabel.cs: -------------------------------------------------------------------------------- 1 | using System.Windows; 2 | using System.Windows.Controls; 3 | using System.Windows.Media; 4 | 5 | namespace PackageManager.Views.Controls 6 | { 7 | public class CompatibilityLabel : ContentControl 8 | { 9 | public bool IsCompatible 10 | { 11 | get => (bool)GetValue(IsCompatibleProperty); 12 | set => SetValue(IsCompatibleProperty, value); 13 | } 14 | 15 | public static readonly DependencyProperty IsCompatibleProperty = DependencyProperty.Register( 16 | "IsCompatible", 17 | typeof(bool), 18 | typeof(CompatibilityLabel), 19 | new PropertyMetadata(true, OnIsCompatibleChanged) 20 | ); 21 | 22 | private static void OnIsCompatibleChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) 23 | { 24 | CompatibilityLabel view = (CompatibilityLabel)d; 25 | view.UpdateVisibility(); 26 | } 27 | 28 | public CompatibilityLabel() 29 | { 30 | CreateContent(); 31 | UpdateVisibility(); 32 | } 33 | 34 | private void CreateContent() 35 | { 36 | Content = new TextBlock() 37 | { 38 | Text = " (Not compatible)", 39 | ToolTip = "Installed version is not compatible with current a version of the application.", 40 | Foreground = new SolidColorBrush(Colors.Red) 41 | }; 42 | } 43 | 44 | private void UpdateVisibility() 45 | => Visibility = IsCompatible ? Visibility.Collapsed : Visibility.Visible; 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/PackageManager.UI/Views/Controls/TabControl.cs: -------------------------------------------------------------------------------- 1 | using System.Windows; 2 | using System.Windows.Controls; 3 | using System.Windows.Controls.Primitives; 4 | 5 | namespace PackageManager.Views.Controls 6 | { 7 | public class TabControl 8 | { 9 | public static int GetLastSelectedIndex(DependencyObject obj) 10 | => (int)obj.GetValue(LastSelectedIndexProperty); 11 | 12 | public static void SetLastSelectedIndex(DependencyObject obj, int value) 13 | => obj.SetValue(LastSelectedIndexProperty, value); 14 | 15 | public static readonly DependencyProperty LastSelectedIndexProperty = DependencyProperty.RegisterAttached( 16 | "LastSelectedIndex", 17 | typeof(int), 18 | typeof(TabControl), 19 | new PropertyMetadata(-1) 20 | ); 21 | 22 | 23 | public static bool GetIsAutoFocus(DependencyObject obj) 24 | => (bool)obj.GetValue(IsAutoFocusProperty); 25 | 26 | public static void SetIsAutoFocus(DependencyObject obj, bool value) 27 | => obj.SetValue(IsAutoFocusProperty, value); 28 | 29 | public static readonly DependencyProperty IsAutoFocusProperty = DependencyProperty.RegisterAttached( 30 | "IsAutoFocus", 31 | typeof(bool), 32 | typeof(TabControl), 33 | new PropertyMetadata(false, OnIsAutoFocusChanged) 34 | ); 35 | 36 | private static void OnIsAutoFocusChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) 37 | { 38 | Selector view = (Selector)d; 39 | bool isAutoFocus = (bool)e.NewValue; 40 | if (isAutoFocus) 41 | { 42 | view.SelectionChanged += OnSelectionChanged; 43 | TabSelected(view, view.SelectedIndex); 44 | } 45 | else 46 | { 47 | view.SelectionChanged -= OnSelectionChanged; 48 | } 49 | } 50 | 51 | 52 | private static void OnSelectionChanged(object sender, SelectionChangedEventArgs e) 53 | { 54 | Selector view = (Selector)sender; 55 | TabSelected(view, view.SelectedIndex); 56 | } 57 | 58 | private static void TabSelected(Selector sender, int index) 59 | { 60 | if (GetLastSelectedIndex(sender) == index) 61 | return; 62 | 63 | SetLastSelectedIndex(sender, index); 64 | 65 | ContentControl item = (ContentControl)sender.Items[index]; 66 | UIElement element = (UIElement)item.Content; 67 | 68 | if (element is IAutoFocus autoFocus) 69 | autoFocus.Focus(); 70 | else 71 | element.Focus(); 72 | } 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /src/PackageManager.UI/Views/Converters/BoolConverter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel; 3 | using System.Globalization; 4 | using System.Windows.Data; 5 | 6 | namespace PackageManager.Views.Converters 7 | { 8 | public class BoolConverter : IValueConverter 9 | { 10 | [DefaultValue(true)] 11 | public bool Test { get; set; } = true; 12 | public object TrueValue { get; set; } 13 | public object FalseValue { get; set; } 14 | 15 | public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 16 | { 17 | bool? boolValue = value as bool?; 18 | if (boolValue == null) 19 | boolValue = false; 20 | 21 | object result = null; 22 | if (Test == boolValue.Value) 23 | result = TrueValue; 24 | else 25 | result = FalseValue; 26 | 27 | if (targetType != null && result != null) 28 | { 29 | Type resultType = result.GetType(); 30 | TypeConverter converter = TypeDescriptor.GetConverter(targetType); 31 | if (converter != null && converter.CanConvertFrom(resultType)) 32 | result = converter.ConvertFrom(null, CultureInfo.InvariantCulture, result); 33 | } 34 | 35 | return result; 36 | } 37 | 38 | public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) 39 | { 40 | throw new NotImplementedException(); 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/PackageManager.UI/Views/Converters/CuttingConverter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Globalization; 3 | using System.Windows.Data; 4 | 5 | namespace PackageManager.Views.Converters 6 | { 7 | public class CuttingConverter : IValueConverter 8 | { 9 | public int EdgeValue { get; set; } 10 | 11 | public object LowerValue { get; set; } 12 | public object EqualValue { get; set; } 13 | public object GreaterValue { get; set; } 14 | 15 | public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 16 | { 17 | int intValue = (int)value; 18 | if (intValue > EdgeValue) 19 | return GreaterValue; 20 | else if (intValue < EdgeValue) 21 | return LowerValue; 22 | else 23 | return EqualValue; 24 | } 25 | 26 | public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) 27 | { 28 | throw new NotImplementedException(); 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/PackageManager.UI/Views/Converters/DropNewLineConverter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Globalization; 3 | using System.Windows.Data; 4 | 5 | namespace PackageManager.Views.Converters 6 | { 7 | public class DropNewLineConverter : IValueConverter 8 | { 9 | public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 10 | { 11 | string target = value?.ToString(); 12 | if (string.IsNullOrEmpty(target)) 13 | return target; 14 | 15 | target = target.Replace(Environment.NewLine, string.Empty); 16 | target = target.Replace("\n", string.Empty); 17 | return target; 18 | } 19 | 20 | public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) 21 | { 22 | throw new NotImplementedException(); 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/PackageManager.UI/Views/Converters/FirstNotNullMultiConverter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Globalization; 3 | using System.Windows; 4 | using System.Windows.Data; 5 | 6 | namespace PackageManager.Views.Converters 7 | { 8 | public class FirstNotNullMultiConverter : IMultiValueConverter 9 | { 10 | public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture) 11 | { 12 | for (int i = 0; i < values.Length; i++) 13 | { 14 | if (values[i] != null && values[i] != DependencyProperty.UnsetValue) 15 | return values[i]; 16 | } 17 | 18 | return null; 19 | } 20 | 21 | public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture) 22 | { 23 | throw new NotImplementedException(); 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/PackageManager.UI/Views/Converters/FormatConverter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Globalization; 3 | using System.Windows.Data; 4 | 5 | namespace PackageManager.Views.Converters 6 | { 7 | public class FormatConverter : IValueConverter 8 | { 9 | public string Format { get; set; } 10 | 11 | public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 12 | { 13 | IFormattable formattable = value as IFormattable; 14 | if (formattable != null) 15 | return formattable.ToString(Format, culture); 16 | 17 | return value; 18 | } 19 | 20 | public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) 21 | { 22 | throw new NotImplementedException(); 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/PackageManager.UI/Views/Converters/NullConverter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Globalization; 3 | using System.Windows.Data; 4 | 5 | namespace PackageManager.Views.Converters 6 | { 7 | public class NullConverter : IValueConverter 8 | { 9 | public object TrueValue { get; set; } 10 | public object FalseValue { get; set; } 11 | 12 | public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 13 | { 14 | if (value == null) 15 | return TrueValue; 16 | 17 | if (value is string) 18 | { 19 | string stringValue = value as string; 20 | if (stringValue == string.Empty) 21 | return TrueValue; 22 | } 23 | 24 | return FalseValue; 25 | } 26 | 27 | public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) 28 | { 29 | throw new NotImplementedException(); 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/PackageManager.UI/Views/Converters/NullValueConverter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Globalization; 3 | using System.Windows.Data; 4 | 5 | namespace PackageManager.Views.Converters 6 | { 7 | public class NullValueConverter : IValueConverter 8 | { 9 | public object DefaultValue { get; set; } 10 | 11 | public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 12 | { 13 | if (value == null) 14 | return DefaultValue; 15 | 16 | return value; 17 | } 18 | 19 | public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) 20 | { 21 | throw new NotImplementedException(); 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/PackageManager.UI/Views/Converters/SelfPackageConverter.cs: -------------------------------------------------------------------------------- 1 | using PackageManager.Models; 2 | using PackageManager.Services; 3 | using System; 4 | using System.Globalization; 5 | using System.Windows.Data; 6 | 7 | namespace PackageManager.Views.Converters 8 | { 9 | public class SelfPackageConverter : IValueConverter 10 | { 11 | public static SelfPackageConfiguration Configuration { get; set; } 12 | 13 | public object TrueValue { get; set; } 14 | public object FalseValue { get; set; } 15 | 16 | public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 17 | { 18 | if (IsSelfPackage(value)) 19 | return TrueValue; 20 | 21 | return FalseValue; 22 | } 23 | 24 | private static bool IsSelfPackage(object value) 25 | { 26 | if (Configuration == null) 27 | return false; 28 | 29 | string packageId = value as string; 30 | if (packageId == null) 31 | { 32 | var package = value as IPackageIdentity; 33 | if (package == null) 34 | return false; 35 | 36 | packageId = package.Id; 37 | } 38 | 39 | return Configuration.Equals(packageId); 40 | } 41 | 42 | public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) 43 | { 44 | throw new NotImplementedException(); 45 | } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/PackageManager.UI/Views/Converters/ValidUrlToTrueConverter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Globalization; 3 | using System.Windows.Data; 4 | 5 | namespace PackageManager.Views.Converters 6 | { 7 | public class ValidUrlToTrueConverter : IValueConverter 8 | { 9 | public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 10 | { 11 | string url = (string)value; 12 | return Uri.TryCreate(url, UriKind.Absolute, out Uri uri); 13 | } 14 | 15 | public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) 16 | { 17 | throw new NotImplementedException(); 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/PackageManager.UI/Views/DesignData/MockInstallService.cs: -------------------------------------------------------------------------------- 1 | using PackageManager.Models; 2 | using PackageManager.Services; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Threading; 6 | using System.Threading.Tasks; 7 | 8 | namespace PackageManager.Views.DesignData 9 | { 10 | internal class MockInstallService : IInstallService 11 | { 12 | public string Path => @"C:\Temp"; 13 | public IPackageIdentity Installed { get; set; } 14 | 15 | public bool IsInstalled(string packageId) 16 | => false; 17 | 18 | public bool IsInstalled(IPackageIdentity package) 19 | => string.Equals(Installed?.Id, package?.Id, StringComparison.CurrentCultureIgnoreCase) && string.Equals(Installed?.Version, package?.Version, StringComparison.CurrentCultureIgnoreCase); 20 | 21 | public void Install(IPackageIdentity package) 22 | { } 23 | 24 | public void Uninstall(IPackageIdentity package) 25 | { } 26 | 27 | public Task> GetInstalledAsync(IEnumerable packageSources, CancellationToken cancellationToken) 28 | { 29 | return Task.FromResult>( 30 | new List() 31 | { 32 | ViewModelLocator.IncompatiblePackage, 33 | ViewModelLocator.CompatiblePackage 34 | } 35 | ); 36 | } 37 | 38 | public Task FindInstalledAsync(string packageId, CancellationToken cancellationToken) 39 | { 40 | return null; 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/PackageManager.UI/Views/DesignData/MockInstalledPackage.cs: -------------------------------------------------------------------------------- 1 | using PackageManager.Models; 2 | 3 | namespace PackageManager.Views.DesignData 4 | { 5 | internal class MockInstalledPackage : IInstalledPackage 6 | { 7 | public IPackage Definition { get; } 8 | public bool IsCompatible { get; } 9 | 10 | public MockInstalledPackage(IPackage definition, bool isCompatible) 11 | { 12 | Definition = definition; 13 | IsCompatible = isCompatible; 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/PackageManager.UI/Views/DesignData/MockPackage.cs: -------------------------------------------------------------------------------- 1 | using PackageManager.Models; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Threading; 5 | using System.Threading.Tasks; 6 | 7 | namespace PackageManager.Views.DesignData 8 | { 9 | internal class MockPackage : IPackage 10 | { 11 | public string Id { get; set; } 12 | public string Version { get; set; } 13 | public string Description { get; set; } 14 | 15 | public string Authors { get; set; } 16 | public DateTime? Published { get; set; } 17 | public string Tags { get; set; } 18 | 19 | public Uri IconUrl { get; set; } 20 | public Uri ProjectUrl { get; set; } 21 | public Uri LicenseUrl { get; set; } 22 | 23 | public bool Equals(IPackageIdentity other) 24 | { 25 | if (other == null) 26 | return false; 27 | 28 | return string.Equals(Id, other.Id, StringComparison.CurrentCultureIgnoreCase) && string.Equals(Version, other.Version, StringComparison.CurrentCultureIgnoreCase); 29 | } 30 | 31 | public bool Equals(IPackage other) 32 | => Equals((IPackageIdentity)other); 33 | 34 | public Task GetContentAsync(CancellationToken cancellationToken) 35 | { 36 | throw new NotImplementedException(); 37 | } 38 | 39 | public Task> GetVersionsAsync(bool isPrereleaseIncluded, CancellationToken cancellationToken) 40 | { 41 | throw new NotImplementedException(); 42 | } 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/PackageManager.UI/Views/DesignData/MockPackageSource.cs: -------------------------------------------------------------------------------- 1 | using PackageManager.Models; 2 | using System; 3 | 4 | namespace PackageManager.Views.DesignData 5 | { 6 | public class MockPackageSource : IPackageSource 7 | { 8 | public string Name { get; } 9 | public Uri Uri { get; } 10 | 11 | public MockPackageSource(string name, Uri uri) 12 | { 13 | Name = name; 14 | Uri = uri; 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/PackageManager.UI/Views/DesignData/MockPackageSourceBuilder.cs: -------------------------------------------------------------------------------- 1 | using PackageManager.Models; 2 | using System; 3 | 4 | namespace PackageManager.Views.DesignData 5 | { 6 | public class MockPackageSourceBuilder : IPackageSourceBuilder 7 | { 8 | private readonly MockPackageSourceCollection service; 9 | private string name; 10 | private Uri uri; 11 | 12 | public MockPackageSourceBuilder(MockPackageSourceCollection service) 13 | { 14 | this.service = service; 15 | } 16 | 17 | public IPackageSourceBuilder Name(string name) 18 | { 19 | this.name = name; 20 | return this; 21 | } 22 | 23 | public IPackageSourceBuilder Uri(Uri uri) 24 | { 25 | this.uri = uri; 26 | return this; 27 | } 28 | 29 | public IPackageSource Save() 30 | { 31 | var source = new MockPackageSource(name, uri); 32 | service.all.Add(source); 33 | service.RaiseChanged(); 34 | return source; 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/PackageManager.UI/Views/DesignData/MockPackageSourceCollection.cs: -------------------------------------------------------------------------------- 1 | using Neptuo; 2 | using PackageManager.Models; 3 | using System; 4 | using System.Collections.Generic; 5 | 6 | namespace PackageManager.Views.DesignData 7 | { 8 | public class MockPackageSourceCollection : IPackageSourceCollection 9 | { 10 | internal readonly List all = new List(); 11 | private IPackageSource primary; 12 | 13 | public IPackageSource Primary => primary; 14 | public IReadOnlyCollection All => all; 15 | 16 | public event Action Changed; 17 | 18 | internal void RaiseChanged() => Changed?.Invoke(); 19 | 20 | public IPackageSource Add(string name, Uri uri) 21 | { 22 | var source = new MockPackageSource(name, uri); 23 | all.Add(source); 24 | RaiseChanged(); 25 | return source; 26 | } 27 | 28 | public IPackageSourceBuilder Add() 29 | => new MockPackageSourceBuilder(this); 30 | 31 | public IPackageSourceBuilder Edit(IPackageSource source) 32 | => new MockPackageSourceBuilder(this); 33 | 34 | public void MarkAsPrimary(IPackageSource source) 35 | { 36 | primary = source; 37 | RaiseChanged(); 38 | } 39 | 40 | public void Remove(IPackageSource source) 41 | { 42 | all.Remove((MockPackageSource)source); 43 | RaiseChanged(); 44 | } 45 | 46 | public int MoveUp(IPackageSource source) 47 | => throw Ensure.Exception.NotSupported(); 48 | 49 | public int MoveDown(IPackageSource source) 50 | => throw Ensure.Exception.NotSupported(); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/PackageManager.UI/Views/DesignData/MockPackageSourceProvider.cs: -------------------------------------------------------------------------------- 1 | using PackageManager.Models; 2 | using PackageManager.ViewModels; 3 | using System; 4 | using System.Collections.Generic; 5 | 6 | namespace PackageManager.Views.DesignData 7 | { 8 | public class MockPackageSourceProvider : IPackageSourceSelector 9 | { 10 | public IEnumerable Sources => new List(1) { new MockPackageSource("NuGet.org", new Uri("https://api.nuget.org/v3/index.json", UriKind.Absolute)) }; 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/PackageManager.UI/Views/DesignData/MockSearchService.cs: -------------------------------------------------------------------------------- 1 | using PackageManager.Models; 2 | using PackageManager.Services; 3 | using System.Collections.Generic; 4 | using System.Threading; 5 | using System.Threading.Tasks; 6 | 7 | namespace PackageManager.Views.DesignData 8 | { 9 | internal class MockSearchService : ISearchService 10 | { 11 | public Task> SearchAsync(IEnumerable packageSources, string searchText, SearchOptions options = default, CancellationToken cancellationToken = default) 12 | { 13 | return Task.FromResult>(new List() 14 | { 15 | ViewModelLocator.Package 16 | }); 17 | } 18 | 19 | public Task FindLatestVersionAsync(IEnumerable packageSources, IPackage package, bool isPrereleaseIncluded, CancellationToken cancellationToken = default) 20 | { 21 | return Task.FromResult(ViewModelLocator.Package); 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/PackageManager.UI/Views/DesignData/MockSelfUpdateService.cs: -------------------------------------------------------------------------------- 1 | using PackageManager.Models; 2 | using PackageManager.Services; 3 | 4 | namespace PackageManager.Views.DesignData 5 | { 6 | public class MockSelfUpdateService : ISelfUpdateService 7 | { 8 | public bool IsSelfUpdate { get; set; } 9 | 10 | public void RunNewInstance(IPackage package) 11 | { } 12 | 13 | public void Update(IPackage latest) 14 | { } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/PackageManager.UI/Views/IAutoFocus.cs: -------------------------------------------------------------------------------- 1 | namespace PackageManager.Views 2 | { 3 | public interface IAutoFocus 4 | { 5 | void Focus(); 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /src/PackageManager.UI/Views/Installed.xaml.cs: -------------------------------------------------------------------------------- 1 | using PackageManager.Models; 2 | using PackageManager.ViewModels; 3 | using System.Windows; 4 | using System.Windows.Controls; 5 | 6 | namespace PackageManager.Views 7 | { 8 | public partial class Installed : UserControl, IAutoFocus 9 | { 10 | public InstalledViewModel ViewModel 11 | { 12 | get { return (InstalledViewModel)GetValue(ViewModelProperty); } 13 | set { SetValue(ViewModelProperty, value); } 14 | } 15 | 16 | public static readonly DependencyProperty ViewModelProperty = DependencyProperty.Register( 17 | "ViewModel", 18 | typeof(InstalledViewModel), 19 | typeof(Installed), 20 | new PropertyMetadata(null, OnViewModelChanged) 21 | ); 22 | 23 | private static void OnViewModelChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) 24 | { 25 | Installed view = (Installed)d; 26 | view.OnViewModelChanged((InstalledViewModel)e.OldValue, (InstalledViewModel)e.NewValue); 27 | } 28 | 29 | 30 | internal IInstalledPackage SelectedPackage 31 | { 32 | get { return (IInstalledPackage)GetValue(SelectedPackageProperty); } 33 | set { SetValue(SelectedPackageProperty, value); } 34 | } 35 | 36 | internal static readonly DependencyProperty SelectedPackageProperty = DependencyProperty.Register( 37 | "SelectedPackage", 38 | typeof(IInstalledPackage), 39 | typeof(Installed), 40 | new PropertyMetadata(null) 41 | ); 42 | 43 | public Installed() 44 | { 45 | InitializeComponent(); 46 | } 47 | 48 | private void OnViewModelChanged(InstalledViewModel oldValue, InstalledViewModel newValue) 49 | { 50 | if (oldValue != null) 51 | oldValue.Uninstall.Completed += OnRefresh; 52 | 53 | MainPanel.DataContext = newValue; 54 | 55 | if (newValue != null) 56 | newValue.Uninstall.Completed += OnRefresh; 57 | } 58 | 59 | private void OnRefresh() 60 | => ViewModel.Refresh.Execute(); 61 | 62 | void IAutoFocus.Focus() 63 | { 64 | ViewModel.Refresh.Execute(); 65 | lvwPackages.Focus(); 66 | } 67 | 68 | private void lvwPackages_SelectionChanged(object sender, SelectionChangedEventArgs e) 69 | { 70 | ViewModel.Uninstall.RaiseCanExecuteChanged(); 71 | ViewModel.Reinstall.RaiseCanExecuteChanged(); 72 | } 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /src/PackageManager.UI/Views/Loading.xaml: -------------------------------------------------------------------------------- 1 |  7 | 8 | 9 | 10 | 11 | 12 |