public void VsTextViewCreated(IVsTextView textViewAdapter) { IWpfTextView textView = EditorAdaptersFactoryService.GetWpfTextView(textViewAdapter); if (!DocumentService.TryGetTextDocument(textView.TextBuffer, out ITextDocument doc)) { return; } string fileName = Path.GetFileName(doc.FilePath); if (!fileName.Equals(Constants.ConfigFileName, StringComparison.OrdinalIgnoreCase)) { return; } new CompletionController(textViewAdapter, textView, CompletionBroker); _dependencies = Dependencies.FromConfigFile(doc.FilePath); _manifest = Manifest.FromFileAsync(doc.FilePath, _dependencies, CancellationToken.None).Result; _manifestPath = doc.FilePath; _project = VsHelpers.GetDTEProjectFromConfig(_manifestPath); if (_manifest == null) { AddErrorToList(PredefinedErrors.ManifestMalformed()); } doc.FileActionOccurred += OnFileSaved; textView.Closed += OnViewClosed; }
public void Predefined() { TestError(PredefinedErrors.UnknownException(), "LIB000"); TestError(PredefinedErrors.ProviderUnknown("_prov_"), "LIB001", "_prov_"); TestError(PredefinedErrors.UnableToResolveSource("_libid_", "_prov_"), "LIB002", "_libid_", "_prov_"); TestError(PredefinedErrors.CouldNotWriteFile("file.js"), "LIB003", "file.js"); TestError(PredefinedErrors.ManifestMalformed(), "LIB004"); }
private async Task UninstallLibraryAsync(string configFilePath, string libraryName, string version, string providerId, CancellationToken cancellationToken) { string libraryId = LibraryIdToNameAndVersionConverter.Instance.GetLibraryId(libraryName, version, providerId); Logger.LogEventsHeader(OperationType.Uninstall, libraryId); try { Stopwatch sw = new Stopwatch(); sw.Start(); var dependencies = _dependenciesFactory.FromConfigFile(configFilePath); Manifest manifest = await Manifest.FromFileAsync(configFilePath, dependencies, cancellationToken).ConfigureAwait(false); ILibraryOperationResult result = null; if (manifest == null) { result = LibraryOperationResult.FromError(PredefinedErrors.ManifestMalformed()); } else { IHostInteraction hostInteraction = dependencies.GetHostInteractions(); result = await manifest.UninstallAsync(libraryName, version, async (filesPaths) => await hostInteraction.DeleteFilesAsync(filesPaths, cancellationToken), cancellationToken).ConfigureAwait(false); } sw.Stop(); if (result.Errors.Any()) { Logger.LogErrorsSummary(new List <ILibraryOperationResult> { result }, OperationType.Uninstall); } else { Logger.LogEventsSummary(new List <ILibraryOperationResult> { result }, OperationType.Uninstall, sw.Elapsed); } Telemetry.LogEventsSummary(new List <ILibraryOperationResult> { result }, OperationType.Uninstall, sw.Elapsed); } catch (OperationCanceledException ex) { Logger.LogEvent(string.Format(LibraryManager.Resources.Text.Uninstall_LibraryCancelled, libraryId), LogLevel.Task); Telemetry.TrackException($@"{OperationType.Uninstall}Cancelled", ex); } }
#pragma warning restore CA1819 // Properties should not return arrays public override bool Execute() { Logger.Instance.Clear(); var configFilePath = new FileInfo(Path.Combine(ProjectDirectory, FileName)); if (!configFilePath.Exists) { Log.LogWarning(configFilePath.Name + " does not exist"); return(true); } var sw = new Stopwatch(); sw.Start(); CancellationToken token = CancellationToken.None; Log.LogMessage(MessageImportance.High, Environment.NewLine + Resources.Text.Restore_OperationStarted); var dependencies = Dependencies.FromTask(ProjectDirectory, ProviderAssemblies.Select(pa => new FileInfo(pa.ItemSpec).FullName)); Manifest manifest = Manifest.FromFileAsync(configFilePath.FullName, dependencies, token).Result; var logger = dependencies.GetHostInteractions().Logger as Logger; if (manifest == null) { sw.Stop(); LogErrors(new[] { PredefinedErrors.ManifestMalformed() }); FlushLogger(logger); return(false); } IEnumerable <ILibraryOperationResult> validationResults = manifest.GetValidationResultsAsync(token).Result; if (!validationResults.All(r => r.Success)) { sw.Stop(); LogErrors(validationResults.SelectMany(r => r.Errors)); return(false); } IEnumerable <ILibraryOperationResult> results = manifest.RestoreAsync(token).Result; sw.Stop(); FlushLogger(logger); PopulateFilesWritten(results, dependencies.GetHostInteractions()); LogResults(sw, results); return(!Log.HasLoggedErrors); }
protected async Task <Manifest> GetManifestAsync() { if (!File.Exists(Settings.ManifestFileName)) { throw new InvalidOperationException(string.Format(Resources.Text.LibmanJsonNotFound, Settings.ManifestFileName)); } Manifest manifest = await Manifest.FromFileAsync(Settings.ManifestFileName, ManifestDependencies, CancellationToken.None); if (manifest == null) { Logger.Log(PredefinedErrors.ManifestMalformed().Message, LogLevel.Error); throw new InvalidOperationException(Resources.Text.FixManifestFile); } return(manifest); }
public void Constructor() { Mocks.LibraryInstallationState state = GetState(); var ctor1 = new LibraryInstallationResult(state); Assert.AreEqual(state, ctor1.InstallationState); Assert.AreEqual(0, ctor1.Errors.Count); Assert.IsTrue(ctor1.Success); Assert.IsFalse(ctor1.Cancelled); var ctor2 = new LibraryInstallationResult(state, PredefinedErrors.ManifestMalformed()); Assert.AreEqual(state, ctor2.InstallationState); Assert.AreEqual(1, ctor2.Errors.Count); Assert.IsFalse(ctor2.Success); Assert.IsFalse(ctor2.Cancelled); }
/// <summary> /// Creates an instance of the <see cref="Manifest"/> class based on /// the provided JSON string. /// </summary> /// <param name="json">A string of JSON in the correct format.</param> /// <param name="dependencies">The host provided dependencies.</param> /// <returns></returns> internal static Manifest FromJson(string json, IDependencies dependencies) { try { Manifest manifest = JsonConvert.DeserializeObject <Manifest>(json); manifest._dependencies = dependencies; manifest._hostInteraction = dependencies.GetHostInteractions(); UpdateLibraryProviderAndDestination(manifest); return(manifest); } catch (Exception) { dependencies.GetHostInteractions().Logger.Log(PredefinedErrors.ManifestMalformed().Message, LogLevel.Task); return(null); } }
/// <summary> /// Creates an instance of the <see cref="Manifest"/> class based on /// the provided JSON string. /// </summary> /// <param name="json">A string of JSON in the correct format.</param> /// <param name="dependencies">The host provided dependencies.</param> /// <returns></returns> public static Manifest FromJson(string json, IDependencies dependencies) { try { Manifest manifest = JsonConvert.DeserializeObject <Manifest>(json); manifest._dependencies = dependencies; manifest._hostInteraction = dependencies.GetHostInteractions(); foreach (LibraryInstallationState state in manifest.Libraries.Cast <LibraryInstallationState>()) { state.ProviderId = state.ProviderId ?? manifest.DefaultProvider; } return(manifest); } catch (Exception) { dependencies.GetHostInteractions().Logger.Log(PredefinedErrors.ManifestMalformed().Message, LogLevel.Task); return(null); } }
private void OnFileSaved(object sender, TextDocumentFileActionEventArgs e) { var textDocument = sender as ITextDocument; if (e.FileActionType == FileActionTypes.ContentSavedToDisk && textDocument != null) { Task.Run(async() => { try { Manifest newManifest = Manifest.FromJson(textDocument.TextBuffer.CurrentSnapshot.GetText(), _dependencies); if (newManifest != null) { await RemoveFilesAsync(newManifest).ConfigureAwait(false); _manifest = newManifest; await LibraryHelpers.RestoreAsync(textDocument.FilePath, _manifest, CancellationToken.None).ConfigureAwait(false); Telemetry.TrackOperation("restoresave"); } else { AddErrorToList(PredefinedErrors.ManifestMalformed()); } } catch (Exception ex) { string textMessage = string.Concat(Environment.NewLine, LibraryManager.Resources.Text.RestoreHasErrors, Environment.NewLine); Logger.LogEvent(textMessage, LogLevel.Task); Logger.LogEvent(ex.ToString(), LogLevel.Error); Telemetry.TrackException("restoresavefailed", ex); } }); } }
private async Task UninstallLibraryAsync(string configFilePath, string libraryId, CancellationToken cancellationToken) { Logger.LogEventsHeader(OperationType.Uninstall, libraryId); try { Stopwatch sw = new Stopwatch(); sw.Start(); var dependencies = Dependencies.FromConfigFile(configFilePath); Manifest manifest = await Manifest.FromFileAsync(configFilePath, dependencies, cancellationToken).ConfigureAwait(false); ILibraryOperationResult result = null; if (manifest == null) { result = LibraryOperationResult.FromError(PredefinedErrors.ManifestMalformed()); } else { IHostInteraction hostInteraction = dependencies.GetHostInteractions(); result = await manifest.UninstallAsync(libraryId, async (filesPaths) => await hostInteraction.DeleteFilesAsync(filesPaths, cancellationToken), cancellationToken).ConfigureAwait(false); } sw.Stop(); Logger.LogEventsSummary(new List <ILibraryOperationResult> { result }, OperationType.Uninstall, sw.Elapsed); Telemetry.TrackUserTask("libraryuninstall"); } catch (OperationCanceledException) { Logger.LogEvent(string.Format(LibraryManager.Resources.Text.Uninstall_LibraryCancelled, libraryId), LogLevel.Task); } }
private async Task ExecuteAsync(object sender, EventArgs e) { Telemetry.TrackUserTask("Execute-InstallLibraryCommand"); ProjectItem item = await VsHelpers.GetSelectedItemAsync().ConfigureAwait(false); Project project = await VsHelpers.GetProjectOfSelectedItemAsync().ConfigureAwait(false); if (project != null) { string rootFolder = await project.GetRootFolderAsync().ConfigureAwait(false); string configFilePath = Path.Combine(rootFolder, Constants.ConfigFileName); IDependencies dependencies = Dependencies.FromConfigFile(configFilePath); Manifest manifest = await GetManifestAsync(configFilePath, dependencies).ConfigureAwait(false); await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync(); // If the manifest contains errors, we will not invoke the "Add Client-Side libraries" dialog // Instead we will display a message box indicating the syntax errors in manifest file. if (manifest == null) { IVsUIShell shell = Package.GetGlobalService(typeof(SVsUIShell)) as IVsUIShell; int result; shell.ShowMessageBox(dwCompRole: 0, rclsidComp: Guid.Empty, pszTitle: null, pszText: PredefinedErrors.ManifestMalformed().Message, pszHelpFile: null, dwHelpContextID: 0, msgbtn: OLEMSGBUTTON.OLEMSGBUTTON_OK, msgdefbtn: OLEMSGDEFBUTTON.OLEMSGDEFBUTTON_FIRST, msgicon: OLEMSGICON.OLEMSGICON_WARNING, fSysAlert: 0, pnResult: out result); return; } string target = string.Empty; // Install command was invoked from a folder. // So the initial target location should be name of the folder from which // the command was invoked. if (item != null) { target = item.FileNames[1]; } else { // Install command was invoked from project scope. // If wwwroot exists, initial target location should be - wwwroot/lib. // Else, target location should be - lib if (Directory.Exists(Path.Combine(rootFolder, "wwwroot"))) { target = Path.Combine(rootFolder, "wwwroot", "lib") + Path.DirectorySeparatorChar; } else { target = Path.Combine(rootFolder, "lib") + Path.DirectorySeparatorChar; } } UI.InstallDialog dialog = new UI.InstallDialog(dependencies, _libraryCommandService, configFilePath, target, rootFolder, project); var dte = (DTE)Package.GetGlobalService(typeof(SDTE)); int hwnd = dte.MainWindow.HWnd; WindowInteropHelper windowInteropHelper = new WindowInteropHelper(dialog); // Set visual studio window's handle as the owner of the dialog. // This will remove the dialog from alt-tab list and will not allow the user to switch the dialog box to the background windowInteropHelper.Owner = new IntPtr(hwnd); dialog.ShowDialog(); Telemetry.TrackUserTask("Open-InstallDialog"); } }
private async Task ExecuteAsync(object sender, EventArgs e) { Telemetry.TrackUserTask("Execute-InstallLibraryCommand"); ProjectItem item = await VsHelpers.GetSelectedItemAsync().ConfigureAwait(false); Project project = await VsHelpers.GetProjectOfSelectedItemAsync().ConfigureAwait(false); if (project != null) { string rootFolder = await project.GetRootFolderAsync().ConfigureAwait(false); string configFilePath = Path.Combine(rootFolder, Constants.ConfigFileName); IDependencies dependencies = _dependenciesFactory.FromConfigFile(configFilePath); Manifest manifest = await GetManifestAsync(configFilePath, dependencies).ConfigureAwait(false); await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync(); // If the manifest contains errors, we will not invoke the "Add Client-Side libraries" dialog // Instead we will display a message box indicating the syntax errors in manifest file. if (manifest == null) { IVsUIShell shell = Package.GetGlobalService(typeof(SVsUIShell)) as IVsUIShell; int result; shell.ShowMessageBox(dwCompRole: 0, rclsidComp: Guid.Empty, pszTitle: null, pszText: PredefinedErrors.ManifestMalformed().Message, pszHelpFile: null, dwHelpContextID: 0, msgbtn: OLEMSGBUTTON.OLEMSGBUTTON_OK, msgdefbtn: OLEMSGDEFBUTTON.OLEMSGDEFBUTTON_FIRST, msgicon: OLEMSGICON.OLEMSGICON_WARNING, fSysAlert: 0, pnResult: out result); return; } string target = string.Empty; // Install command was invoked from a folder. // So the initial target location should be name of the folder from which // the command was invoked. if (item != null) { target = item.FileNames[1]; } else { // Install command was invoked from project scope. // If wwwroot exists, initial target location should be - wwwroot/lib. // Else, target location should be - lib if (Directory.Exists(Path.Combine(rootFolder, "wwwroot"))) { target = Path.Combine(rootFolder, "wwwroot", "lib") + Path.DirectorySeparatorChar; } else { target = Path.Combine(rootFolder, "lib") + Path.DirectorySeparatorChar; } } string initialTargetLocation = CalculateSuggestedInstallPath(target, rootFolder); var selectedProviderBinding = new SelectedProviderBinding(); var libraryIdViewModel = new LibraryIdViewModel(new ProviderCatalogSearchService(() => selectedProviderBinding.SelectedProvider), string.Empty); var libraryNameBinding = new LibraryNameBinding(); var targetLocationViewModel = new TargetLocationViewModel(initialTargetLocation, libraryNameBinding, new LocationSearchService(dependencies.GetHostInteractions())); var dialogViewModel = new InstallDialogViewModel( _libraryCommandService, configFilePath, dependencies, libraryIdViewModel, targetLocationViewModel, selectedProviderBinding, libraryNameBinding, target, project); var dialog = new UI.InstallDialog(dialogViewModel); dialog.ShowModal(); Telemetry.TrackUserTask("Open-InstallDialog"); } }
/// <summary> /// Returns a collection of <see cref="ILibraryOperationResult"/> that represents the status for validation of the Manifest and its libraries /// </summary> /// <param name="manifest">The <see cref="Manifest"/> to be validated</param> /// <param name="dependencies"><see cref="IDependencies"/>used to validate the libraries</param> /// <param name="cancellationToken"></param> /// <returns></returns> public static async Task <IEnumerable <ILibraryOperationResult> > GetManifestErrorsAsync( Manifest manifest, IDependencies dependencies, CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); if (manifest == null) { return(new ILibraryOperationResult[] { LibraryOperationResult.FromError(PredefinedErrors.ManifestMalformed()) }); } if (!IsValidManifestVersion(manifest.Version)) { return(new ILibraryOperationResult[] { LibraryOperationResult.FromError(PredefinedErrors.VersionIsNotSupported(manifest.Version)) }); } return(await GetLibrariesErrorsAsync(manifest.Libraries, dependencies, manifest.DefaultDestination, manifest.DefaultProvider, cancellationToken)); }