public async Task SaveAsync_Success() { var manifest = new Manifest(_dependencies); IProvider provider = _dependencies.GetProvider("cdnjs"); var desiredState = new LibraryInstallationState { LibraryId = "[email protected]", ProviderId = "cdnjs", DestinationPath = "lib", Files = new[] { "jquery.min.js" } }; ILibraryInstallationResult result = await provider.InstallAsync(desiredState, CancellationToken.None).ConfigureAwait(false); Assert.IsTrue(result.Success); manifest.AddLibrary(desiredState); await manifest.SaveAsync(_filePath, CancellationToken.None).ConfigureAwait(false); Manifest newManifest = await Manifest.FromFileAsync(_filePath, _dependencies, CancellationToken.None).ConfigureAwait(false); Assert.IsTrue(File.Exists(_filePath)); Assert.AreEqual(manifest.Libraries.Count(), newManifest.Libraries.Count()); Assert.AreEqual(manifest.Version, newManifest.Version); }
/// <summary> /// Installs a library with the given libraryId /// </summary> /// <param name="libraryName"></param> /// <param name="version"></param> /// <param name="providerId"></param> /// <param name="files"></param> /// <param name="destination"></param> /// <param name="cancellationToken"></param> /// <returns></returns> public async Task <IEnumerable <ILibraryOperationResult> > InstallLibraryAsync( string libraryName, string version, string providerId, IReadOnlyList <string> files, string destination, CancellationToken cancellationToken) { ILibraryOperationResult result; var desiredState = new LibraryInstallationState() { Name = libraryName, Version = version, Files = files, ProviderId = providerId, DestinationPath = destination }; UpdateLibraryProviderAndDestination(desiredState, DefaultProvider, DefaultDestination); ILibraryOperationResult validationResult = await desiredState.IsValidAsync(_dependencies); if (!validationResult.Success) { return(new [] { validationResult }); } IProvider provider = _dependencies.GetProvider(desiredState.ProviderId); if (provider == null) { return(new [] { new LibraryOperationResult(desiredState, new IError[] { PredefinedErrors.ProviderUnknown(desiredState.ProviderId) }) }); } IEnumerable <ILibraryOperationResult> conflictResults = await CheckLibraryForConflictsAsync(desiredState, cancellationToken).ConfigureAwait(false); if (!conflictResults.All(r => r.Success)) { return(conflictResults); } result = await provider.InstallAsync(desiredState, cancellationToken).ConfigureAwait(false); if (result.Success) { AddLibrary(desiredState); } return(new [] { result }); }
public async Task InstallAsync() { IProvider provider = _dependencies.GetProvider("filesystem"); var desiredState = new LibraryInstallationState { ProviderId = "filesystem", LibraryId = _file1, DestinationPath = "lib", Files = new[] { "file1.txt" } }; ILibraryInstallationResult result = await provider.InstallAsync(desiredState, CancellationToken.None); Assert.IsTrue(result.Success, "Didn't install"); string copiedFile = Path.Combine(_projectFolder, desiredState.DestinationPath, desiredState.Files[0]); Assert.IsTrue(File.Exists(copiedFile), "File1 wasn't copied"); var manifest = Manifest.FromJson("{}", _dependencies); manifest.AddLibrary(desiredState); await manifest.SaveAsync(_configFilePath, CancellationToken.None); Assert.IsTrue(File.Exists(_configFilePath)); Assert.AreEqual(File.ReadAllText(copiedFile), "test content"); }
public async Task EndToEndTestAsync() { IProvider provider = _dependencies.GetProvider("cdnjs"); ILibraryCatalog catalog = provider.GetCatalog(); // Search for libraries to display in search result IReadOnlyList <ILibraryGroup> groups = await catalog.SearchAsync("jquery", 4, CancellationToken.None); Assert.AreEqual(4, groups.Count); // Show details for selected library ILibraryGroup group = groups.FirstOrDefault(); Assert.AreEqual("jquery", group.DisplayName); Assert.IsNotNull(group.Description); // Get all libraries in group to display version list IEnumerable <string> libraryIds = await group.GetLibraryIdsAsync(CancellationToken.None); Assert.IsTrue(libraryIds.Count() >= 67); Assert.AreEqual("[email protected]", libraryIds.Last(), "Library version mismatch"); // Get the library to install ILibrary library = await catalog.GetLibraryAsync(libraryIds.First(), CancellationToken.None); Assert.AreEqual(group.DisplayName, library.Name); var desiredState = new LibraryInstallationState { LibraryId = "[email protected]", ProviderId = "cdnjs", DestinationPath = "lib", Files = new[] { "jquery.js", "jquery.min.js" } }; // Install library ILibraryInstallationResult result = await provider.InstallAsync(desiredState, CancellationToken.None).ConfigureAwait(false); foreach (string file in desiredState.Files) { string absolute = Path.Combine(_projectFolder, desiredState.DestinationPath, file); Assert.IsTrue(File.Exists(absolute)); } Assert.IsTrue(result.Success); Assert.IsFalse(result.Cancelled); Assert.AreSame(desiredState, result.InstallationState); Assert.AreEqual(0, result.Errors.Count); }
/// <summary> /// Restores all libraries in the <see cref="Libraries"/> collection. /// </summary> /// <param name="cancellationToken">A token that allows for cancellation of the operation.</param> public async Task <IEnumerable <ILibraryInstallationResult> > RestoreAsync(CancellationToken cancellationToken) { //TODO: This should have an "undo scope" var results = new List <ILibraryInstallationResult>(); var tasks = new List <Task <ILibraryInstallationResult> >(); if (!IsValidManifestVersion(Version)) { results.Add(LibraryInstallationResult.FromErrors(new IError[] { PredefinedErrors.VersionIsNotSupported(Version) })); return(results); } foreach (ILibraryInstallationState state in Libraries) { if (cancellationToken.IsCancellationRequested) { results.Add(LibraryInstallationResult.FromCancelled(state)); _hostInteraction.Logger.Log(Resources.Text.RestoreCancelled, LogLevel.Task); return(results); } if (!state.IsValid(out IEnumerable <IError> errors)) { results.Add(new LibraryInstallationResult(state, errors.ToArray())); continue; } _hostInteraction.Logger.Log(string.Format(Resources.Text.RestoringLibrary, state.LibraryId), LogLevel.Operation); IProvider provider = _dependencies.GetProvider(state.ProviderId); if (provider != null) { tasks.Add(provider.InstallAsync(state, cancellationToken)); } else { results.Add(new LibraryInstallationResult(state, PredefinedErrors.ProviderUnknown(state.ProviderId))); } } await Task.WhenAll(tasks).ConfigureAwait(false); results.AddRange(tasks.Select(t => t.Result)); return(results); }
/// <summary> /// Expands the files property for each library /// </summary> /// <param name="libraries"></param> /// <param name="dependencies"></param> /// <param name="defaultDestination"></param> /// <param name="defaultProvider"></param> /// <param name="cancellationToken"></param> /// <returns></returns> private static async Task <IEnumerable <ILibraryOperationResult> > ExpandLibrariesAsync( IEnumerable <ILibraryInstallationState> libraries, IDependencies dependencies, string defaultDestination, string defaultProvider, CancellationToken cancellationToken) { List <ILibraryOperationResult> expandedLibraries = new List <ILibraryOperationResult>(); foreach (ILibraryInstallationState library in libraries) { cancellationToken.ThrowIfCancellationRequested(); string installDestination = string.IsNullOrEmpty(library.DestinationPath) ? defaultDestination : library.DestinationPath; string providerId = string.IsNullOrEmpty(library.ProviderId) ? defaultProvider : library.ProviderId; IProvider provider = dependencies.GetProvider(providerId); if (provider == null) { return(new[] { LibraryOperationResult.FromError(PredefinedErrors.ProviderIsUndefined()) }); } ILibraryOperationResult desiredState = await provider.UpdateStateAsync(library, cancellationToken); if (!desiredState.Success) { return(new[] { desiredState }); } expandedLibraries.Add(desiredState); } return(expandedLibraries); }
public void Setup() { _cacheFolder = Environment.ExpandEnvironmentVariables(@"%localappdata%\Microsoft\Library\"); _projectFolder = Path.Combine(Path.GetTempPath(), "LibraryInstaller"); var hostInteraction = new HostInteraction(_projectFolder, _cacheFolder); _dependencies = new Dependencies(hostInteraction, new CdnjsProviderFactory()); _provider = _dependencies.GetProvider("cdnjs"); Directory.CreateDirectory(_projectFolder); }
public void Setup() { _cacheFolder = Environment.ExpandEnvironmentVariables(@"%localappdata%\Microsoft\Library\"); _projectFolder = Path.Combine(Path.GetTempPath(), "LibraryManager"); var hostInteraction = new HostInteraction(_projectFolder, _cacheFolder); _dependencies = new Dependencies(hostInteraction, new CdnjsProviderFactory()); _provider = _dependencies.GetProvider("cdnjs"); LibraryIdToNameAndVersionConverter.Instance.EnsureInitialized(_dependencies); Directory.CreateDirectory(_projectFolder); }
/// <summary> /// Validates <see cref="ILibraryInstallationState"/> /// </summary> /// <param name="state">The <see cref="ILibraryInstallationState"/> to validate.</param> /// <param name="dependencies">The <see cref="IDependencies"/> used to validate <see cref="ILibraryInstallationState"/></param> /// <returns><see cref="ILibraryOperationResult"/> with the result of the validation</returns> public static async Task <ILibraryOperationResult> IsValidAsync(this ILibraryInstallationState state, IDependencies dependencies) { if (state == null) { return(new LibraryOperationResult(state, new[] { PredefinedErrors.UnknownError() })); } if (string.IsNullOrEmpty(state.ProviderId)) { return(new LibraryOperationResult(state, new[] { PredefinedErrors.ProviderIsUndefined() })); } IProvider provider = dependencies.GetProvider(state.ProviderId); if (provider == null) { return(new LibraryOperationResult(state, new[] { PredefinedErrors.ProviderUnknown(state.ProviderId) })); } return(await IsValidAsync(state, provider).ConfigureAwait(false)); }
public override void Invoke(CancellationToken cancellationToken) { Telemetry.TrackUserTask("Invoke-UpdateSuggestedAction"); if (_disabled) { return; } try { IDependencies dependencies = _provider.DependenciesFactory.FromConfigFile(_provider.ConfigFilePath); IProvider provider = dependencies.GetProvider(_provider.InstallationState.ProviderId); ILibraryCatalog catalog = provider?.GetCatalog(); if (catalog == null) { return; } SortedNodeList <Node> children = JsonHelpers.GetChildren(_provider.LibraryObject); MemberNode member = children.OfType <MemberNode>().FirstOrDefault(m => m.UnquotedNameText == ManifestConstants.Library); if (member != null) { using (ITextEdit edit = TextBuffer.CreateEdit()) { edit.Replace(new Span(member.Value.Start, member.Value.Width), "\"" + _updatedLibraryId + "\""); edit.Apply(); } } } catch (Exception ex) { Logger.LogEvent(ex.ToString(), LogLevel.Error); Telemetry.TrackException("UpdateSuggestedActionFailed", ex); } }
protected override IEnumerable <JsonCompletionEntry> GetEntries(JsonCompletionContext context) { MemberNode member = context.ContextNode.FindType <MemberNode>(); if (member == null || member.UnquotedNameText != "files") { yield break; } var parent = member.Parent as ObjectNode; if (!JsonHelpers.TryGetInstallationState(parent, out ILibraryInstallationState state)) { yield break; } if (string.IsNullOrEmpty(state.Name)) { yield break; } IDependencies dependencies = _dependenciesFactory.FromConfigFile(ConfigFilePath); IProvider provider = dependencies.GetProvider(state.ProviderId); ILibraryCatalog catalog = provider?.GetCatalog(); if (catalog == null) { yield break; } Task <ILibrary> task = catalog.GetLibraryAsync(state.Name, state.Version, CancellationToken.None); FrameworkElement presenter = GetPresenter(context); IEnumerable <string> usedFiles = GetUsedFiles(context); if (task.IsCompleted) { if (!(task.Result is ILibrary library)) { yield break; } foreach (string file in library.Files.Keys) { if (!usedFiles.Contains(file)) { ImageMoniker glyph = WpfUtil.GetImageMonikerForFile(file); yield return(new SimpleCompletionEntry(file, glyph, context.Session)); } } } else { yield return(new SimpleCompletionEntry(Resources.Text.Loading, string.Empty, KnownMonikers.Loading, context.Session)); _ = task.ContinueWith(async(t) => { await VisualStudio.Shell.ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync(); if (!(t.Result is ILibrary library)) { return; } if (!context.Session.IsDismissed) { var results = new List <JsonCompletionEntry>(); foreach (string file in library.Files.Keys) { if (!usedFiles.Contains(file)) { ImageMoniker glyph = WpfUtil.GetImageMonikerForFile(file); results.Add(new SimpleCompletionEntry(file, glyph, context.Session)); } } UpdateListEntriesSync(context, results); } }, TaskScheduler.Default); } }
protected override IEnumerable <JsonCompletionEntry> GetEntries(JsonCompletionContext context) { var member = context.ContextNode as MemberNode; if (member == null || member.UnquotedNameText != ManifestConstants.Library) { yield break; } var parent = member.Parent as ObjectNode; if (!JsonHelpers.TryGetInstallationState(parent, out ILibraryInstallationState state)) { yield break; } IDependencies dependencies = _dependenciesFactory.FromConfigFile(ConfigFilePath); IProvider provider = dependencies.GetProvider(state.ProviderId); ILibraryCatalog catalog = provider?.GetCatalog(); if (catalog == null) { yield break; } // member.Value is null when there is no value yet, e.g. when typing a space at "library":| // where | represents caret position. In this case, set caretPosition to "1" to short circuit execution of this function // and return no entries (member.UnquotedValueText will be empty string in that case). int caretPosition = member.Value != null ? context.Session.TextView.Caret.Position.BufferPosition - member.Value.Start - 1 : 1; if (caretPosition > member.UnquotedValueText.Length) { yield break; } Task <CompletionSet> task = catalog.GetLibraryCompletionSetAsync(member.UnquotedValueText, caretPosition); int count = 0; if (!context.Session.Properties.ContainsProperty(CompletionController.RetriggerCompletion)) { context.Session.Properties.AddProperty(CompletionController.RetriggerCompletion, true); } if (task.IsCompleted) { CompletionSet completionSet = task.Result; if (completionSet.Completions != null) { List <JsonCompletionEntry> results = GetCompletionList(member, context, completionSet, count); foreach (JsonCompletionEntry completionEntry in results) { yield return(completionEntry); } } } else { yield return(new SimpleCompletionEntry(Resources.Text.Loading, string.Empty, KnownMonikers.Loading, context.Session)); _ = task.ContinueWith((t) => { if (!t.IsCanceled || !t.IsFaulted) { if (!context.Session.IsDismissed) { CompletionSet completionSet = t.Result; if (completionSet.Completions != null) { List <JsonCompletionEntry> results = GetCompletionList(member, context, completionSet, count); UpdateListEntriesSync(context, results); } } } }, TaskScheduler.Default); } }