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 });
        }
Beispiel #3
0
        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);
        }
Beispiel #5
0
        /// <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);
        }
Beispiel #6
0
        /// <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);
        }
Beispiel #9
0
        /// <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);
            }
        }