protected override void UpgradeProject(ref ProjectRootElement projectXml, ref ProjectRootElement userProjectXml, Action <__VSUL_ERRORLEVEL, string> log) { var envVarsProp = projectXml.Properties.FirstOrDefault(p => p.Name == NodejsConstants.EnvironmentVariables); if (envVarsProp != null) { var globals = projectXml.PropertyGroups.FirstOrDefault() ?? projectXml.AddPropertyGroup(); AddOrSetProperty(globals, NodejsConstants.Environment, envVarsProp.Value.Replace(";", "\r\n")); envVarsProp.Parent.RemoveChild(envVarsProp); log(__VSUL_ERRORLEVEL.VSUL_INFORMATIONAL, SR.GetString(SR.UpgradedEnvironmentVariables)); } }
public async Task <ExecutionResult> Execute(IReplWindow window, string arguments) { string projectPath = string.Empty; string npmArguments = arguments.Trim(' ', '\t'); // Parse project name/directory in square brackets if (npmArguments.StartsWith("[", StringComparison.Ordinal)) { var match = Regex.Match(npmArguments, @"(?:[[]\s*\""?\s*)(.*?)(?:\s*\""?\s*[]]\s*)"); projectPath = match.Groups[1].Value; npmArguments = npmArguments.Substring(match.Length); } // Include spaces on either side of npm arguments so that we can more simply detect arguments // at beginning and end of string (e.g. '--global') npmArguments = string.Format(CultureInfo.InvariantCulture, " {0} ", npmArguments); // Prevent running `npm init` without the `-y` flag since it will freeze the repl window, // waiting for user input that will never come. if (npmArguments.Contains(" init ") && !(npmArguments.Contains(" -y ") || npmArguments.Contains(" --yes "))) { window.WriteError(SR.GetString(SR.ReplWindowNpmInitNoYesFlagWarning)); return(ExecutionResult.Failure); } var solution = Package.GetGlobalService(typeof(SVsSolution)) as IVsSolution; IEnumerable <IVsProject> loadedProjects = solution.EnumerateLoadedProjects(onlyNodeProjects: false); var projectNameToDirectoryDictionary = new Dictionary <string, Tuple <string, IVsHierarchy> >(StringComparer.OrdinalIgnoreCase); foreach (IVsProject project in loadedProjects) { var hierarchy = (IVsHierarchy)project; object extObject; var projectResult = hierarchy.GetProperty(VSConstants.VSITEMID_ROOT, (int)__VSHPROPID.VSHPROPID_ExtObject, out extObject); if (!ErrorHandler.Succeeded(projectResult)) { continue; } EnvDTE.Project dteProject = extObject as EnvDTE.Project; if (dteProject == null) { continue; } string projectName = dteProject.Name; if (string.IsNullOrEmpty(projectName)) { continue; } // Try checking the `ProjectHome` property first EnvDTE.Properties properties = dteProject.Properties; if (dteProject.Properties != null) { EnvDTE.Property projectHome = null; try { projectHome = properties.Item("ProjectHome"); } catch (ArgumentException) { // noop } if (projectHome != null) { var projectHomeDirectory = projectHome.Value as string; if (!string.IsNullOrEmpty(projectHomeDirectory)) { projectNameToDirectoryDictionary.Add(projectName, Tuple.Create(projectHomeDirectory, hierarchy)); continue; } } } // Otherwise, fall back to using fullname string projectDirectory = string.IsNullOrEmpty(dteProject.FullName) ? null : Path.GetDirectoryName(dteProject.FullName); if (!string.IsNullOrEmpty(projectDirectory)) { projectNameToDirectoryDictionary.Add(projectName, Tuple.Create(projectDirectory, hierarchy)); } } Tuple <string, IVsHierarchy> projectInfo; if (string.IsNullOrEmpty(projectPath) && projectNameToDirectoryDictionary.Count == 1) { projectInfo = projectNameToDirectoryDictionary.Values.First(); } else { projectNameToDirectoryDictionary.TryGetValue(projectPath, out projectInfo); } NodejsProjectNode nodejsProject = null; if (projectInfo != null) { projectPath = projectInfo.Item1; if (projectInfo.Item2 != null) { nodejsProject = projectInfo.Item2.GetProject().GetNodejsProject(); } } bool isGlobalCommand = false; if (string.IsNullOrWhiteSpace(npmArguments) || npmArguments.Contains(" -g ") || npmArguments.Contains(" --global ")) { projectPath = Environment.GetFolderPath(Environment.SpecialFolder.UserProfile); isGlobalCommand = true; } // In case someone copies filename string projectDirectoryPath = File.Exists(projectPath) ? Path.GetDirectoryName(projectPath) : projectPath; if (!isGlobalCommand && !Directory.Exists(projectDirectoryPath)) { window.WriteError("Please specify a valid Node.js project or project directory. If your solution contains multiple projects, specify a target project using .npm [ProjectName or ProjectDir] <npm arguments> For example: .npm [MyApp] list"); return(ExecutionResult.Failure); } string npmPath; try { npmPath = NpmHelpers.GetPathToNpm( nodejsProject != null ? Nodejs.GetAbsoluteNodeExePath( nodejsProject.ProjectHome, nodejsProject.GetProjectProperty(NodeProjectProperty.NodeExePath)) : null); } catch (NpmNotFoundException) { Nodejs.ShowNodejsNotInstalled(); return(ExecutionResult.Failure); } var npmReplRedirector = new NpmReplRedirector(window); await ExecuteNpmCommandAsync( npmReplRedirector, npmPath, projectDirectoryPath, new[] { npmArguments }, null); if (npmReplRedirector.HasErrors) { window.WriteError(SR.GetString(SR.NpmReplCommandCompletedWithErrors, arguments)); } else { window.WriteLine(SR.GetString(SR.NpmSuccessfullyCompleted, arguments)); } if (nodejsProject != null) { await nodejsProject.CheckForLongPaths(npmArguments); } return(ExecutionResult.Success); }
private OutputWindowRedirector GetNpmOutputPane() { try { #if DEV14_OR_LATER return(OutputWindowRedirector.Get(_projectNode.Site, VSPackageManagerPaneGuid, "Bower/npm")); #else return(OutputWindowRedirector.Get(_projectNode.Site, NpmOutputPaneGuid, SR.GetString(SR.NpmOutputPaneTitle))); #endif } catch (InvalidOperationException) { return(null); } }
public async Task CheckForLongPaths(string npmArguments = null) { if (_isCheckingForLongPaths || !NodejsPackage.Instance.GeneralOptionsPage.CheckForLongPaths) { return; } if (npmArguments != null && _uninstallRegex.IsMatch(npmArguments)) { return; } try { _isCheckingForLongPaths = true; TaskDialogButton dedupeButton, ignoreButton, disableButton; var taskDialog = new TaskDialog(NodejsPackage.Instance) { AllowCancellation = true, EnableHyperlinks = true, Title = SR.GetString(SR.LongPathWarningTitle), MainIcon = TaskDialogIcon.Warning, Content = SR.GetString(SR.LongPathWarningText), CollapsedControlText = SR.GetString(SR.LongPathShowPathsExceedingTheLimit), ExpandedControlText = SR.GetString(SR.LongPathHidePathsExceedingTheLimit), Buttons = { (dedupeButton = new TaskDialogButton(SR.GetString(SR.LongPathNpmDedupe), SR.GetString(SR.LongPathNpmDedupeDetail))), (ignoreButton = new TaskDialogButton(SR.GetString(SR.LongPathDoNothingButWarnNextTime))), (disableButton = new TaskDialogButton(SR.GetString(SR.LongPathDoNothingAndDoNotWarnAgain), SR.GetString(SR.LongPathDoNothingAndDoNotWarnAgainDetail))) }, FooterIcon = TaskDialogIcon.Information, Footer = SR.GetString(SR.LongPathFooter) }; taskDialog.HyperlinkClicked += (sender, e) => { switch (e.Url) { case "#msdn": Process.Start("http://go.microsoft.com/fwlink/?LinkId=454508"); break; case "#uservoice": Process.Start("http://go.microsoft.com/fwlink/?LinkID=456509"); break; case "#help": Process.Start("http://go.microsoft.com/fwlink/?LinkId=456511"); break; default: System.Windows.Clipboard.SetText(e.Url); break; } }; recheck: var longPaths = await Task.Factory.StartNew(() => GetLongSubPaths(ProjectHome) .Concat(GetLongSubPaths(_intermediateOutputPath)) .Select(lpi => string.Format("• {1}\u00A0<a href=\"{0}\">{2}</a>", lpi.FullPath, lpi.RelativePath, SR.GetString(SR.LongPathClickToCopy))) .ToArray()); if (longPaths.Length == 0) { return; } taskDialog.ExpandedInformation = string.Join("\r\n", longPaths); var button = taskDialog.ShowModal(); if (button == dedupeButton) { var repl = NodejsPackage.Instance.OpenReplWindow(focus: false); await repl.ExecuteCommand(".npm dedupe").HandleAllExceptions(SR.ProductName); taskDialog.Content += "\r\n\r\n" + SR.GetString(SR.LongPathNpmDedupeDidNotHelp); taskDialog.Buttons.Remove(dedupeButton); goto recheck; } else if (button == disableButton) { var page = NodejsPackage.Instance.GeneralOptionsPage; page.CheckForLongPaths = false; page.SaveSettingsToStorage(); } } finally { _isCheckingForLongPaths = false; } }