chr
2026-04-05 fe750b791d5b517cc4e9bc8e99a9a75139a0cfba
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
//            Copyright Keysight Technologies 2012-2019
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, you can obtain one at http://mozilla.org/MPL/2.0/.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.IO;
using System.Linq;
using System.Xml.Serialization;
 
namespace OpenTap.Package
{
    /// <summary>
    /// Settings class containing plugin package manager settings
    /// </summary>
    [Display("Package Manager")]
    [Browsable(false)]
    [HelpLink("EditorHelp.chm::/Package Manager Help/Readme.html")]
    public class PackageManagerSettings : ComponentSettings<PackageManagerSettings>
    {
        /// <summary>
        /// Creates a new PackageManagerSettings. 
        /// User code should use PackageManagerSettings.Current to access the singleton instead of constructing a new object.
        /// </summary>
        public PackageManagerSettings()
        {
            Repositories = new List<RepositorySettingEntry>();
            Repositories.Add(new RepositorySettingEntry { IsEnabled = true, Url = new Uri(Path.GetFullPath(ExecutorClient.ExeDir)).LocalPath });
            Repositories.Add(new RepositorySettingEntry { IsEnabled = true, Url = "https://packages.opentap.io" });
            UseLocalPackageCache = true;
        }
 
        /// <summary>
        /// When true a packages cached in the user-wide package cache (shared accross installations, but not accross users) is used when in addition to the repositories specified in <see cref="Repositories"/>.
        /// </summary>
        [Display("Use Local Package Cache", Group: "Package Repositories", Order: 3, Description: "Use package cache (shared across installations, but not across users) in addition to repositories specified here.")]
        public bool UseLocalPackageCache { get; set; }
 
        /// <summary>
        /// When true a package management UI should also list packages that are not compatible with the current installation.
        /// </summary>
        [Display("Show Incompatible Packages", Group: "General", Description: "Show all packages, including incompatible and deprecated packages.")]
        public bool ShowIncompatiblePackages { get; set; }
 
        /// <summary>
        /// Determines whether tap.exe will run an update check against configured repositories at startup.
        /// </summary>
        [Display("Check for Updates at Startup", Group: "General", Description: "Checks for updates against enabled package repositories. The update check sends anonymized package idenfiers to the enabled repositories.")]
        public bool CheckForUpdates { get; set; } = true;
 
        /// <summary>
        /// Specifies how a UI should order a list of different version of the same package name. Can be either by version or build date.
        /// </summary>
        [System.Xml.Serialization.XmlIgnore]
        [Browsable(false)]
        [Display("Sort Package Details By", Group: "General", Description: "Sorts the selected package's other versions, shown in the details window.")]
        public PackageSort Sort { get; set; }
 
        /// <summary>
        /// Specifies how a UI should order a list of different version of the same package name. Can be either by version or build date.
        /// </summary>
        public enum PackageSort
        {
            /// <summary> Sort packages by version number. </summary>
            Version,
            /// <summary> Sort packages by build date. </summary>
            Date
        }
 
        /// <summary>
        /// List of servers from where new plugin packages can be discovered and downloaded.
        /// </summary>
        [Display("URLs", Group: "Package Repositories", Order: 2, Description: "URLs or file-system paths from where plugin packages can be found. Example: https://packages.opentap.io")]
        [Layout(LayoutMode.FullRow)]
        public List<RepositorySettingEntry> Repositories { get; set; }
 
        /// <summary>
        /// Get an IPackageRepository for each of the repos defined in <see cref="Repositories"/> plus one for the cache if <see cref="UseLocalPackageCache"/> is enabled.
        /// </summary>
        /// <returns></returns>
        internal List<IPackageRepository> GetEnabledRepositories(IEnumerable<string> cliSpecifiedRepoUrls = null)
        {
            var repositories = new List<IPackageRepository>();
            if (UseLocalPackageCache)
            {
                var cacheUri =
                    new Uri(PackageCacheHelper.PackageCacheDirectory).AbsoluteUri;
                if ((cliSpecifiedRepoUrls?.Contains(cacheUri) == true) == false)
                    repositories.Add(PackageRepositoryHelpers.DetermineRepositoryType(cacheUri));
            }
 
            if (cliSpecifiedRepoUrls == null)
                repositories.AddRange(Repositories.Where(p => p.IsEnabled && p.Manager != null).Select(s => s.Manager).ToList());
            else
            {
                foreach (var repo in cliSpecifiedRepoUrls)
                    repositories.Add(PackageRepositoryHelpers.DetermineRepositoryType(repo));
            }
            return repositories;
        }
    }
 
    /// <summary>
    /// Structure used by PackageRepositories setting
    /// </summary>
    public class RepositorySettingEntry : ValidatingObject
    {
        string _Url;
        /// <summary>
        /// URL to the server
        /// </summary>
        [Display("URL", Description: "Specify URL to a local or remote repository hosting OpenTAP plugin packages.")]
        public string Url
        {
            get
            {
                return _Url;
            }
            set
            {
                if (_Url == value)
                    return;
                _Url = value;
                _Manager = null; // invalidate the cached manager, now that the URL changed
                OnPropertyChanged("Url");
                OnPropertyChanged("Error");
            }
        }
 
        private bool _IsEnabled;
        /// <summary>
        /// If disabled this server will not be contacted when discovering available plugins.
        /// </summary>
        public bool IsEnabled
        {
            get
            {
                return _IsEnabled;
            }
            set
            {
                if (_IsEnabled == value)
                    return;
                _IsEnabled = value;
                _Manager = null;
                OnPropertyChanged("IsEnabled");
                OnPropertyChanged("Error");
            }
        }
 
        // a cached manager
        IPackageRepository _Manager = null;
 
        /// <summary>
        /// Get a cached instance of IPackageRepository that can query the repository that this RepositorySettingEntry represents. 
        /// </summary>
        /// <value></value>
        public IPackageRepository Manager
        {
            get
            {
                if (_Manager == null)
                {
                    if (String.IsNullOrEmpty(Url))
                        return null;
                    _Manager = PackageRepositoryHelpers.DetermineRepositoryType(Url);
                }
                return _Manager;
            }
        }
 
        /// <summary>
        /// Obsolete. Always false.
        /// </summary>
        [Browsable(false)]
        [XmlIgnore]
        [Obsolete]
        public bool IsBusy { get; set; }
    }
}