/// <summary> /// Returns a command-line for executing the "0install run" command. /// Generates and returns a stub EXE if possible, falls back to directly pointing to the "0install" EXE otherwise. /// </summary> /// <param name="target">The application to be launched.</param> /// <param name="command">The command argument to be passed to the the "0install run" command; can be <c>null</c>.</param> /// <param name="machineWide"><c>true</c> place the generated stub in a machine-wide location; <c>false</c> to place it in the current user profile.</param> /// <exception cref="OperationCanceledException">The user canceled the task.</exception> /// <exception cref="InvalidOperationException">There was a compilation error while generating the stub EXE.</exception> /// <exception cref="IOException">A problem occurred while writing to the filesystem.</exception> /// <exception cref="WebException">A problem occurred while downloading additional data (such as icons).</exception> /// <exception cref="UnauthorizedAccessException">Write access to the filesystem is not permitted.</exception> public IReadOnlyList <string> GetRunCommandLine(FeedTarget target, string?command = null, bool machineWide = false) { string targetKey = target.Uri + "#" + command; var entryPoint = target.Feed.GetEntryPoint(command); bool gui = entryPoint is not { NeedsTerminal : true }; string targetHash = targetKey.Hash(SHA256.Create()); string exeName = (entryPoint == null) ? FeedUri.Escape(target.Feed.Name) : entryPoint.BinaryName ?? entryPoint.Command; string path = Path.Combine( IntegrationManager.GetDir(machineWide, "stubs", targetHash), exeName + ".exe"); #if !DEBUG try #endif { CreateOrUpdateRunStub(path, target, gui, command); return(new[] { path }); } #if !DEBUG catch (Exception ex) { var exe = GetExe(gui); Log.Error($"Failed to generate stub EXE for {targetKey}. Falling back to using '{exe}' directly.", ex); return(GetArguments(target.Uri, command, gui) .Prepend(Path.Combine(Locations.InstallBase, exe)) .ToList()); } #endif }
/// <inheritdoc/> public void Add(FeedUri feedUri, byte[] data) { #region Sanity checks if (feedUri == null) { throw new ArgumentNullException("feedUri"); } if (data == null) { throw new ArgumentNullException("data"); } #endregion // Add to underlying cache _backingCache.Add(feedUri, data); // Add to memory cache (replacing existing old versions) var feed = XmlStorage.LoadXml <Feed>(new MemoryStream(data)); feed.Normalize(feedUri); string key = feedUri.Escape(); lock (_feedDictionary) { _feedDictionary.Remove(key); _feedDictionary.Add(key, feed); } }
/// <inheritdoc/> public void Add(FeedUri feedUri, byte[] data) { #region Sanity checks if (feedUri == null) { throw new ArgumentNullException(nameof(feedUri)); } if (data == null) { throw new ArgumentNullException(nameof(data)); } #endregion if (!Directory.Exists(Path)) { Directory.CreateDirectory(Path); } try { string path = System.IO.Path.Combine(Path, feedUri.Escape()); Log.Debug($"Adding feed {feedUri.ToStringRfc()} to disk cache: {path}"); WriteToFile(data, path); } catch (PathTooLongException) { Log.Info("File path in feed cache too long. Using hash of feed URI to shorten path."); WriteToFile(data, System.IO.Path.Combine(Path, feedUri.AbsoluteUri.Hash(SHA256.Create()))); } }
/// <summary> /// Returns a command-line for executing the "0install run" command. Generates and returns a stub EXE if possible, falls back to directly pointing to the "0install" binary otherwise. /// </summary> /// <param name="target">The application to be launched.</param> /// <param name="command">The command argument to be passed to the the "0install run" command; can be <c>null</c>.</param> /// <param name="machineWide"><c>true</c> place the generated stub in a machine-wide location; <c>false</c> to place it in the current user profile.</param> /// <returns></returns> /// <exception cref="OperationCanceledException">The user canceled the task.</exception> /// <exception cref="InvalidOperationException">There was a compilation error while generating the stub EXE.</exception> /// <exception cref="IOException">A problem occurred while writing to the filesystem.</exception> /// <exception cref="WebException">A problem occurred while downloading additional data (such as icons).</exception> /// <exception cref="UnauthorizedAccessException">Write access to the filesystem is not permitted.</exception> public IReadOnlyList <string> GetRunCommandLine(FeedTarget target, string?command = null, bool machineWide = false) { var entryPoint = target.Feed.GetEntryPoint(command); bool gui = entryPoint is not { NeedsTerminal : true }; try { #if NETFRAMEWORK string hash = (target.Uri + "#" + command).Hash(SHA256.Create()); string exeName = (entryPoint == null) ? FeedUri.Escape(target.Feed.Name) : entryPoint.BinaryName ?? entryPoint.Command; string path = Path.Combine( IntegrationManager.GetDir(machineWide, "stubs", hash), exeName + ".exe"); CreateOrUpdateRunStub(path, target, gui, command); return(new[] { path }); #else return(GetArguments(target.Uri, command, gui) .Prepend(GetBinary(gui)) .ToList()); #endif } #region Error handling catch (InvalidOperationException ex) { // Wrap exception since only certain exception types are allowed throw new IOException(ex.Message, ex); } #endregion }
/// <inheritdoc/> public string GetPath(FeedUri feedUri) { #region Sanity checks if (feedUri == null) { throw new ArgumentNullException(nameof(feedUri)); } #endregion if (feedUri.IsFile) { throw new KeyNotFoundException("Feed cache does not handle local files: " + feedUri.ToStringRfc()); } string fileName = feedUri.Escape(); string path = Path.Combine(DirectoryPath, fileName); if (FileUtils.ExistsCaseSensitive(path)) { return(path); } else { throw new KeyNotFoundException(string.Format(Resources.FeedNotInCache, feedUri, path)); } }
/// <inheritdoc/> public bool Contains(FeedUri feedUri) { #region Sanity checks if (feedUri == null) throw new ArgumentNullException(nameof(feedUri)); #endregion // Local files are passed through directly if (feedUri.IsFile) return File.Exists(feedUri.LocalPath); return FileUtils.ExistsCaseSensitive(Path.Combine(DirectoryPath, feedUri.Escape())); }
/// <inheritdoc/> public bool Contains(FeedUri feedUri) { #region Sanity checks if (feedUri == null) { throw new ArgumentNullException(nameof(feedUri)); } #endregion return(feedUri.IsFile ? File.Exists(feedUri.LocalPath) : FileUtils.ExistsCaseSensitive(System.IO.Path.Combine(Path, feedUri.Escape()))); }
//--------------------// #region Contains /// <inheritdoc/> public bool Contains(FeedUri feedUri) { #region Sanity checks if (feedUri == null) { throw new ArgumentNullException("feedUri"); } #endregion // Local files are passed through directly if (feedUri.IsFile) { return(File.Exists(feedUri.LocalPath)); } return(FileUtils.ExistsCaseSensitive(Path.Combine(DirectoryPath, feedUri.Escape()))); }
/// <inheritdoc/> public string?GetPath(FeedUri feedUri) { #region Sanity checks if (feedUri == null) { throw new ArgumentNullException(nameof(feedUri)); } #endregion if (feedUri.IsFile) { return(feedUri.LocalPath); } string path = System.IO.Path.Combine(Path, feedUri.Escape()); return(FileUtils.ExistsCaseSensitive(path) ? path : null); }
/// <inheritdoc/> public void Remove(FeedUri feedUri) { #region Sanity checks if (feedUri == null) { throw new ArgumentNullException("feedUri"); } #endregion // Remove from memory cache string key = feedUri.Escape(); lock (_feedDictionary) _feedDictionary.Remove(key); // Remove from underlying cache _backingCache.Remove(feedUri); }
/// <summary> /// Determines the file path used to store a feed with a particular ID. /// </summary> /// <exception cref="KeyNotFoundException">The requested <paramref name="feedUri"/> was not found in the cache.</exception> private string GetPath(FeedUri feedUri) { if (feedUri.IsFile) { return(feedUri.LocalPath); } { string fileName = feedUri.Escape(); string path = Path.Combine(DirectoryPath, fileName); if (FileUtils.ExistsCaseSensitive(path)) { return(path); } else { throw new KeyNotFoundException(string.Format(Resources.FeedNotInCache, feedUri, path)); } } }
/// <summary> /// Builds a stub EXE in a well-known location. Future calls with the same arguments will return the same EXE. /// </summary> /// <param name="target">The application to be launched via the stub.</param> /// <param name="command">The command argument to be passed to the the "0install run" command; can be <c>null</c>.</param> /// <param name="handler">A callback object used when the the user is to be informed about the progress of long-running operations such as downloads.</param> /// <param name="machineWide">Store the stub in a machine-wide directory instead of just for the current user.</param> /// <returns>The path to the generated stub EXE.</returns> /// <exception cref="OperationCanceledException">The user canceled the task.</exception> /// <exception cref="InvalidOperationException">There was a compilation error while generating the stub EXE.</exception> /// <exception cref="IOException">A problem occurs while writing to the filesystem.</exception> /// <exception cref="WebException">A problem occured while downloading additional data (such as icons).</exception> /// <exception cref="InvalidOperationException">Write access to the filesystem is not permitted.</exception> public static string GetRunStub(FeedTarget target, [CanBeNull] string command, [NotNull] ITaskHandler handler, bool machineWide = false) { #region Sanity checks if (handler == null) { throw new ArgumentNullException(nameof(handler)); } #endregion var entryPoint = target.Feed.GetEntryPoint(command); string exeName = (entryPoint != null) ? entryPoint.BinaryName ?? entryPoint.Command : FeedUri.Escape(target.Feed.Name); bool needsTerminal = (entryPoint != null && entryPoint.NeedsTerminal); string hash = (target.Uri + "#" + command).Hash(SHA256.Create()); string path = Path.Combine(Locations.GetIntegrationDirPath("0install.net", machineWide, "desktop-integration", "stubs", hash), exeName + ".exe"); CreateOrUpdateRunStub(target, path, command, needsTerminal, handler); return(path); }
/// <inheritdoc/> public void Add(FeedUri feedUri, byte[] data) { #region Sanity checks if (feedUri == null) throw new ArgumentNullException("feedUri"); if (data == null) throw new ArgumentNullException("data"); #endregion // Add to underlying cache _backingCache.Add(feedUri, data); // Add to memory cache (replacing existing old versions) var feed = XmlStorage.LoadXml<Feed>(new MemoryStream(data)); feed.Normalize(feedUri); string key = feedUri.Escape(); lock (_feedDictionary) { _feedDictionary.Remove(key); _feedDictionary.Add(key, feed); } }
/// <inheritdoc/> public Feed GetFeed(FeedUri feedUri) { #region Sanity checks if (feedUri == null) { throw new ArgumentNullException("feedUri"); } #endregion string key = feedUri.Escape(); lock (_feedDictionary) { if (!_feedDictionary.ContainsKey(key)) { // Add to memory cache if missing Feed feed = _backingCache.GetFeed(feedUri); _feedDictionary.Add(key, feed); return(feed); } // Get from memory cache return(_feedDictionary[key]); } }
/// <summary> /// Builds a stub EXE in a well-known location. Future calls with the same arguments will return the same EXE. /// </summary> /// <param name="target">The application to be launched via the stub.</param> /// <param name="command">The command argument to be passed to the the "0install run" command; can be <c>null</c>.</param> /// <param name="machineWide">Store the stub in a machine-wide directory instead of just for the current user.</param> /// <param name="iconStore">Stores icon files downloaded from the web as local files.</param> /// <returns>The path to the generated stub EXE.</returns> /// <exception cref="OperationCanceledException">The user canceled the task.</exception> /// <exception cref="InvalidOperationException">There was a compilation error while generating the stub EXE.</exception> /// <exception cref="IOException">A problem occurred while writing to the filesystem.</exception> /// <exception cref="WebException">A problem occurred while downloading additional data (such as icons).</exception> /// <exception cref="InvalidOperationException">Write access to the filesystem is not permitted.</exception> public static string GetRunStub(FeedTarget target, string?command, IIconStore iconStore, bool machineWide = false) { #region Sanity checks if (iconStore == null) { throw new ArgumentNullException(nameof(iconStore)); } #endregion var entryPoint = target.Feed.GetEntryPoint(command); string exeName = (entryPoint != null) ? entryPoint.BinaryName ?? entryPoint.Command : FeedUri.Escape(target.Feed.Name); bool needsTerminal = (entryPoint != null && entryPoint.NeedsTerminal); string hash = (target.Uri + "#" + command).Hash(SHA256.Create()); string path = Path.Combine( IntegrationManager.GetDir(machineWide, "stubs", hash), exeName + ".exe"); CreateOrUpdateRunStub(target, path, command, needsTerminal, iconStore); return(path); }
/// <inheritdoc/> public string GetPath(FeedUri feedUri) { #region Sanity checks if (feedUri == null) throw new ArgumentNullException(nameof(feedUri)); #endregion if (feedUri.IsFile) throw new KeyNotFoundException("Feed cache does not handle local files: " + feedUri.ToStringRfc()); string fileName = feedUri.Escape(); string path = Path.Combine(DirectoryPath, fileName); if (FileUtils.ExistsCaseSensitive(path)) return path; else throw new KeyNotFoundException(string.Format(Resources.FeedNotInCache, feedUri, path)); }
/// <summary> /// Determines the file path used to store a feed with a particular ID. /// </summary> /// <exception cref="KeyNotFoundException">The requested <paramref name="feedUri"/> was not found in the cache.</exception> private string GetPath(FeedUri feedUri) { if (feedUri.IsFile) return feedUri.LocalPath; { string fileName = feedUri.Escape(); string path = Path.Combine(DirectoryPath, fileName); if (FileUtils.ExistsCaseSensitive(path)) return path; else throw new KeyNotFoundException(string.Format(Resources.FeedNotInCache, feedUri, path)); } }
/// <inheritdoc/> public void Add(FeedUri feedUri, byte[] data) { #region Sanity checks if (feedUri == null) throw new ArgumentNullException("feedUri"); if (data == null) throw new ArgumentNullException("data"); #endregion if (!Directory.Exists(DirectoryPath)) Directory.CreateDirectory(DirectoryPath); try { string path = Path.Combine(DirectoryPath, feedUri.Escape()); Log.Debug("Adding feed " + feedUri.ToStringRfc() + " to disk cache: " + path); WriteToFile(data, path); } catch (PathTooLongException) { Log.Info("File path in feed cache too long. Using hash of feed URI to shorten path."); WriteToFile(data, Path.Combine(DirectoryPath, feedUri.AbsoluteUri.Hash(SHA256.Create()))); } }
/// <inheritdoc/> public Feed GetFeed(FeedUri feedUri) { #region Sanity checks if (feedUri == null) throw new ArgumentNullException("feedUri"); #endregion string key = feedUri.Escape(); lock (_feedDictionary) { if (!_feedDictionary.ContainsKey(key)) { // Add to memory cache if missing Feed feed = _backingCache.GetFeed(feedUri); _feedDictionary.Add(key, feed); return feed; } // Get from memory cache return _feedDictionary[key]; } }
/// <inheritdoc/> public void Remove(FeedUri feedUri) { #region Sanity checks if (feedUri == null) throw new ArgumentNullException("feedUri"); #endregion // Remove from memory cache string key = feedUri.Escape(); lock (_feedDictionary) _feedDictionary.Remove(key); // Remove from underlying cache _backingCache.Remove(feedUri); }