/// <summary> /// Exports all implementations listed in a <see cref="Selections"/> document as archives. /// </summary> /// <param name="implementationStore">Used to get cached implementations.</param> /// <param name="handler">A callback object used when the the user needs to be asked questions or informed about download and IO tasks.</param> /// <exception cref="OperationCanceledException">The user canceled the task.</exception> /// <exception cref="UnauthorizedAccessException">The file could not be read or written.</exception> /// <exception cref="UnauthorizedAccessException">Write access to the directory is not permitted.</exception> /// <exception cref="IOException">An implementation archive could not be creates.</exception> public void ExportImplementations(IImplementationStore implementationStore, ITaskHandler handler) { if (implementationStore == null) { throw new ArgumentNullException(nameof(implementationStore)); } if (handler == null) { throw new ArgumentNullException(nameof(handler)); } string contentDir = Path.Combine(_destination, "content"); Directory.CreateDirectory(contentDir); foreach (var digest in _selections.Implementations.Select(x => x.ManifestDigest).Where(x => x.Best != null).Distinct()) { string?sourcePath = implementationStore.GetPath(digest); if (sourcePath == null) { Log.Warn("Implementation " + digest + " missing from cache"); continue; } using var generator = ArchiveGenerator.Create(sourcePath, Path.Combine(contentDir, digest.Best + ".tbz2"), Archive.MimeTypeTarBzip); handler.RunTask(generator); } }
/// <summary> /// Creates a new store management window. /// </summary> /// <param name="store">The <see cref="IImplementationStore"/> to manage.</param> /// <param name="feedCache">Information about implementations found in the <paramref name="store"/> are extracted from here.</param> public StoreManageForm(IImplementationStore store, IFeedCache feedCache) { _store = store ?? throw new ArgumentNullException(nameof(store)); _feedCache = feedCache ?? throw new ArgumentNullException(nameof(feedCache)); InitializeComponent(); buttonRunAsAdmin.AddShieldIcon(); HandleCreated += delegate { if (Locations.IsPortable || ZeroInstallInstance.IsRunningFromCache) { WindowsTaskbar.PreventPinning(Handle); } if (Locations.IsPortable) { Text += @" - " + Resources.PortableMode; } if (WindowsUtils.IsAdministrator) { Text += @" (Administrator)"; } else if (WindowsUtils.HasUac) { buttonRunAsAdmin.Visible = true; } }; Shown += async delegate { await RefreshListAsync(); }; _treeView.SelectedEntryChanged += OnSelectedEntryChanged; _treeView.CheckedEntriesChanged += OnCheckedEntriesChanged; splitContainer.Panel1.Controls.Add(_treeView); }
/// <summary> /// Creates a new store management window. /// </summary> /// <param name="store">The <see cref="IImplementationStore"/> to manage.</param> /// <param name="feedCache">Information about implementations found in the <paramref name="store"/> are extracted from here.</param> public StoreManageForm(IImplementationStore store, IFeedCache feedCache) { _store = store ?? throw new ArgumentNullException(nameof(store)); _feedCache = feedCache ?? throw new ArgumentNullException(nameof(feedCache)); InitializeComponent(); buttonRunAsAdmin.AddShieldIcon(); HandleCreated += delegate { Program.ConfigureTaskbar(this, Text, subCommand: ".Store.Manage", arguments: StoreMan.Name + " manage"); if (Locations.IsPortable) { Text += @" - " + Resources.PortableMode; } if (WindowsUtils.IsAdministrator) { Text += @" (Administrator)"; } else if (WindowsUtils.HasUac) { buttonRunAsAdmin.Visible = true; } }; Shown += delegate { RefreshList(); }; _treeView.SelectedEntryChanged += OnSelectedEntryChanged; _treeView.CheckedEntriesChanged += OnCheckedEntriesChanged; splitContainer.Panel1.Controls.Add(_treeView); }
/// <summary> /// Creates a new <see cref="SelectionCandidate"/> provider. /// </summary> /// <param name="config">User settings controlling network behaviour, solving, etc.</param> /// <param name="feedManager">Provides access to remote and local <see cref="Feed"/>s. Handles downloading, signature verification and caching.</param> /// <param name="implementationStore">Used to check which <see cref="Implementation"/>s are already cached.</param> /// <param name="packageManager">An external package manager that can install <see cref="PackageImplementation"/>s.</param> public SelectionCandidateProvider(Config config, IFeedManager feedManager, IImplementationStore implementationStore, IPackageManager packageManager) { _config = config ?? throw new ArgumentNullException(nameof(config)); if (feedManager == null) { throw new ArgumentNullException(nameof(feedManager)); } if (implementationStore == null) { throw new ArgumentNullException(nameof(implementationStore)); } _packageManager = packageManager ?? throw new ArgumentNullException(nameof(packageManager)); _interfacePreferences = new TransparentCache <FeedUri, InterfacePreferences>(InterfacePreferences.LoadForSafe); _externalImplementations = new Dictionary <string, ExternalImplementation>(); _storeContains = new TransparentCache <ManifestDigest, bool>(implementationStore.Contains); _feeds = new TransparentCache <FeedUri, Feed?>(feedUri => { try { var feed = feedManager[feedUri]; if (feed.MinInjectorVersion != null && ImplementationVersion.ZeroInstall < feed.MinInjectorVersion) { Log.Warn($"The Zero Install version is too old. The feed '{feedUri}' requires at least version {feed.MinInjectorVersion} but the installed version is {ImplementationVersion.ZeroInstall}. Try updating Zero Install."); return(null); } return(feed); } catch (WebException ex) { Log.Warn(ex); return(null); } }); }
/// <summary> /// Determines the local path of an implementation. /// </summary> /// <param name="implementationStore">The store to get the implementation from.</param> /// <param name="implementation">The implementation to be located.</param> /// <returns>A fully qualified path to the directory containing the implementation.</returns> /// <exception cref="ImplementationNotFoundException">The <paramref name="implementation"/> is not cached yet.</exception> /// <exception cref="UnauthorizedAccessException">Read access to the store is not permitted.</exception> public static string GetPath(this IImplementationStore implementationStore, ImplementationBase implementation) { #region Sanity checks if (implementationStore == null) { throw new ArgumentNullException(nameof(implementationStore)); } if (implementation == null) { throw new ArgumentNullException(nameof(implementation)); } #endregion if (string.IsNullOrEmpty(implementation.LocalPath)) { string?path = implementationStore.GetPath(implementation.ManifestDigest); if (path == null) { throw new ImplementationNotFoundException(implementation.ManifestDigest); } return(path); } else { return(implementation.LocalPath); } }
/// <summary> /// Exports all implementations listed in a <see cref="Selections"/> document as archives. /// </summary> /// <param name="implementationStore">Used to get cached implementations.</param> /// <param name="handler">A callback object used when the the user needs to be asked questions or informed about download and IO tasks.</param> /// <exception cref="OperationCanceledException">The user canceled the task.</exception> /// <exception cref="IOException">An implementation archive could not be created.</exception> /// <exception cref="UnauthorizedAccessException">Read or access to a file is not permitted.</exception> public void ExportImplementations(IImplementationStore implementationStore, ITaskHandler handler) { #region Sanity checks if (implementationStore == null) { throw new ArgumentNullException(nameof(implementationStore)); } if (handler == null) { throw new ArgumentNullException(nameof(handler)); } #endregion foreach (var digest in _selections.Implementations.Select(x => x.ManifestDigest).Where(x => x.Best != null).Distinct()) { string?sourcePath = implementationStore.GetPath(digest); if (sourcePath == null) { Log.Warn($"Implementation {digest} missing from cache"); continue; } using var builder = ArchiveBuilder.Create(Path.Combine(_contentDir, digest.Best + ".tgz"), Archive.MimeTypeTarGzip); handler.RunTask(new ReadDirectory(sourcePath, builder)); } }
/// <summary> /// Creates a new <see cref="SelectionCandidate"/> provider. /// </summary> /// <param name="config">User settings controlling network behaviour, solving, etc.</param> /// <param name="feedManager">Provides access to remote and local <see cref="Feed"/>s. Handles downloading, signature verification and caching.</param> /// <param name="implementationStore">Used to check which <see cref="Implementation"/>s are already cached.</param> /// <param name="packageManager">An external package manager that can install <see cref="PackageImplementation"/>s.</param> public SelectionCandidateProvider(Config config, IFeedManager feedManager, IImplementationStore implementationStore, IPackageManager packageManager) { _config = config ?? throw new ArgumentNullException(nameof(config)); _feedManager = feedManager ?? throw new ArgumentNullException(nameof(feedManager)); _packageManager = packageManager ?? throw new ArgumentNullException(nameof(packageManager)); if (implementationStore == null) { throw new ArgumentNullException(nameof(implementationStore)); } _storeContains = new(implementationStore.Contains); }
/// <summary> /// Creates a new temporary directory node. /// </summary> /// <param name="path">The path of the directory in the store.</param> /// <param name="implementationStore">The <see cref="IImplementationStore"/> the directory is located in.</param> /// <exception cref="FormatException">The manifest file is not valid.</exception> /// <exception cref="IOException">The manifest file could not be read.</exception> /// <exception cref="UnauthorizedAccessException">Read access to the file is not permitted.</exception> public TempDirectoryNode(string path, IImplementationStore implementationStore) : base(implementationStore) { #region Sanity checks if (implementationStore == null) { throw new ArgumentNullException(nameof(implementationStore)); } #endregion Path = path; }
private static IImplementationStore GetProxy() { // Thread-safe singleton with double-check if (_proxy == null) { lock (_lock) { if (_proxy == null) { _proxy = CreateServiceProxy(); } } } return(_proxy); }
/// <summary> /// Removes all implementations from a store. /// </summary> /// <param name="implementationStore">The store to be purged.</param> /// <param name="handler">A callback object used when the the user is to be informed about progress.</param> /// <exception cref="OperationCanceledException">The user canceled the task.</exception> /// <exception cref="IOException">An implementation could not be deleted.</exception> /// <exception cref="UnauthorizedAccessException">Write access to the store is not permitted.</exception> public static void Purge(this IImplementationStore implementationStore, ITaskHandler handler) { #region Sanity checks if (implementationStore == null) { throw new ArgumentNullException(nameof(implementationStore)); } if (handler == null) { throw new ArgumentNullException(nameof(handler)); } #endregion foreach (var manifestDigest in implementationStore.ListAll()) { implementationStore.Remove(manifestDigest, handler); } }
/// <inheritdoc/> public void ManageStore(IImplementationStore store, IFeedCache feedCache) { #region Sanity checks if (store == null) { throw new ArgumentNullException(nameof(store)); } if (feedCache == null) { throw new ArgumentNullException(nameof(feedCache)); } #endregion ThreadUtils.RunSta(() => { using var form = new StoreManageForm(store, feedCache); form.ShowDialog(); }); }
/// <summary> /// Wrapper for <see cref="IImplementationStore.GetPath"/>, handling exceptions. /// </summary> public static string?GetPathSafe(this IImplementationStore implementationStore, ManifestDigest manifestDigest) { #region Sanity checks if (implementationStore == null) { throw new ArgumentNullException(nameof(implementationStore)); } #endregion try { return(implementationStore.GetPath(manifestDigest)); } #region Error handling catch (UnauthorizedAccessException) { return(null); } #endregion }
/// <summary> /// Wrapper for <see cref="IImplementationStore.ListAllTemp"/>, handling exceptions. /// </summary> public static IEnumerable <string> ListAllTempSafe(this IImplementationStore implementationStore) { #region Sanity checks if (implementationStore == null) { throw new ArgumentNullException(nameof(implementationStore)); } #endregion try { return(implementationStore.ListAllTemp()); } #region Error handling catch (UnauthorizedAccessException) { // Ignore authorization errors since listing is not a critical task return(Enumerable.Empty <string>()); } #endregion }
/// <summary> /// Creates a new implementation node. /// </summary> /// <param name="digest">The digest identifying the implementation.</param> /// <param name="implementationStore">The <see cref="IImplementationStore"/> the implementation is located in.</param> /// <exception cref="FormatException">The manifest file is not valid.</exception> /// <exception cref="IOException">The manifest file could not be read.</exception> /// <exception cref="UnauthorizedAccessException">Read access to the file is not permitted.</exception> protected ImplementationNode(ManifestDigest digest, IImplementationStore implementationStore) : base(implementationStore) { #region Sanity checks if (implementationStore == null) { throw new ArgumentNullException(nameof(implementationStore)); } #endregion _digest = digest; // Determine the total size of an implementation via its manifest file string?path = implementationStore.GetPath(digest); if (path == null) { return; } string manifestPath = System.IO.Path.Combine(path, Manifest.ManifestFile); Size = Manifest.Load(manifestPath, ManifestFormat.FromPrefix(digest.AvailableDigests.First())).TotalSize; }
/// <summary> /// Creates a new store node. /// </summary> /// <param name="implementationStore">The store containing the element.</param> protected StoreNode(IImplementationStore implementationStore) { ImplementationStore = implementationStore; }
/// <summary> /// Creates a new orphaned implementation node. /// </summary> /// <param name="digest">The digest identifying the implementation.</param> /// <param name="implementationStore">The <see cref="IImplementationStore"/> the implementation is located in.</param> /// <exception cref="FormatException">The manifest file is not valid.</exception> /// <exception cref="IOException">The manifest file could not be read.</exception> /// <exception cref="UnauthorizedAccessException">Read access to the file is not permitted.</exception> public OrphanedImplementationNode(ManifestDigest digest, IImplementationStore implementationStore) : base(digest, implementationStore) { }
/// <summary> /// Creates a new selections manager /// </summary> /// <param name="feedManager">Used to load <see cref="Feed"/>s containing the original <see cref="Implementation"/>s.</param> /// <param name="implementationStore">The locations to search for cached <see cref="Implementation"/>s.</param> /// <param name="packageManager">An external package manager that can install <see cref="PackageImplementation"/>s.</param> public SelectionsManager(IFeedManager feedManager, IImplementationStore implementationStore, IPackageManager packageManager) { _feedManager = feedManager ?? throw new ArgumentNullException(nameof(feedManager)); _implementationStore = implementationStore ?? throw new ArgumentNullException(nameof(implementationStore)); _packageManager = packageManager ?? throw new ArgumentNullException(nameof(packageManager)); }
/// <summary> /// Creates a new download fetcher. /// </summary> /// <param name="implementationStore">The location to store the downloaded and unpacked <see cref="Implementation"/>s in.</param> /// <param name="handler">A callback object used when the the user needs to be informed about progress.</param> protected FetcherBase(IImplementationStore implementationStore, ITaskHandler handler) { _implementationStore = implementationStore ?? throw new ArgumentNullException(nameof(implementationStore)); Handler = handler ?? throw new ArgumentNullException(nameof(handler)); }
/// <summary> /// Creates a new list builder /// </summary> /// <param name="implementationStore">Used to list <see cref="Implementation"/>s</param> /// <param name="feedCache">Used to load <see cref="Feed"/>s.</param> public CacheNodeBuilder(IImplementationStore implementationStore, IFeedCache feedCache) { _implementationStore = implementationStore ?? throw new ArgumentNullException(nameof(implementationStore)); _feedCache = feedCache ?? throw new ArgumentNullException(nameof(feedCache)); }
/// <summary> /// Creates a new sequential download fetcher. /// </summary> /// <param name="config">User settings controlling network behaviour, solving, etc.</param> /// <param name="implementationStore">The location to store the downloaded and unpacked <see cref="Implementation"/>s in.</param> /// <param name="handler">A callback object used when the the user needs to be informed about progress.</param> public SequentialFetcher(Config config, IImplementationStore implementationStore, ITaskHandler handler) : base(implementationStore, handler) { _config = config ?? throw new ArgumentNullException(nameof(config)); }
/// <summary> /// Creates a new build. /// </summary> /// <param name="implementationStore">Used to locate <see cref="Implementation"/>s.</param> public EnvironmentBuilder(IImplementationStore implementationStore) { _implementationStore = implementationStore ?? throw new ArgumentNullException(nameof(implementationStore)); }
/// <summary> /// Creates a new owned implementation node. /// </summary> /// <param name="digest">The digest identifying the implementation.</param> /// <param name="implementation">Information about the implementation from a <see cref="Feed"/> file.</param> /// <param name="parent">The node of the feed owning the implementation.</param> /// <param name="implementationStore">The <see cref="IImplementationStore"/> the implementation is located in.</param> /// <exception cref="FormatException">The manifest file is not valid.</exception> /// <exception cref="IOException">The manifest file could not be read.</exception> /// <exception cref="UnauthorizedAccessException">Read access to the file is not permitted.</exception> public OwnedImplementationNode(ManifestDigest digest, Implementation implementation, FeedNode parent, IImplementationStore implementationStore) : base(digest, implementationStore) { _parent = parent ?? throw new ArgumentNullException(nameof(parent)); _implementation = implementation ?? throw new ArgumentNullException(nameof(implementation)); }
/// <summary> /// Creates a new executor. /// </summary> /// <param name="implementationStore">Used to locate the selected <see cref="Implementation"/>s.</param> public Executor(IImplementationStore implementationStore) { _implementationStore = implementationStore ?? throw new ArgumentNullException(nameof(implementationStore)); }