// The Default Repository Path that VS uses is hidden in an internal // service 'ISccSettingsService' registered in an internal service // 'ISccServiceHost' in an assembly with no public types that's // always loaded with VS if the git service provider is loaded public string GetLocalClonePathFromGitProvider() { string ret = string.Empty; try { ret = RegistryHelper.PokeTheRegistryForLocalClonePath(); } catch (Exception ex) { VsOutputLogger.WriteLine(string.Format(CultureInfo.CurrentCulture, "Error loading the default cloning path from the registry '{0}'", ex)); } return(ret); }
public static bool Activate() { var windowGuid = new Guid(GitHubPaneGuid); IVsWindowFrame frame; if (ErrorHandler.Failed(Services.UIShell.FindToolWindow((uint)__VSCREATETOOLWIN.CTW_fForceCreate, ref windowGuid, out frame))) { VsOutputLogger.WriteLine("Unable to find or create GitHubPane '" + GitHubPaneGuid + "'"); return(false); } if (ErrorHandler.Failed(frame.Show())) { VsOutputLogger.WriteLine("Unable to show GitHubPane '" + GitHubPaneGuid + "'"); return(false); } return(true); }
void ShowNotification(ILocalRepositoryModel newrepo, string msg) { Guard.ArgumentNotNull(newrepo, nameof(newrepo)); var teServices = ServiceProvider.TryGetService <ITeamExplorerServices>(); teServices.ClearNotifications(); teServices.ShowMessage( msg, new RelayCommand(o => { var str = o.ToString(); /* the prefix is the action to perform: * u: launch browser with url * c: launch create new project dialog * o: launch open existing project dialog */ var prefix = str.Substring(0, 2); if (prefix == "u:") { OpenInBrowser(ServiceProvider.TryGetService <IVisualStudioBrowser>(), new Uri(str.Substring(2))); } else if (prefix == "o:") { if (ErrorHandler.Succeeded(ServiceProvider.GetSolution().OpenSolutionViaDlg(str.Substring(2), 1))) { ServiceProvider.TryGetService <ITeamExplorer>()?.NavigateToPage(new Guid(TeamExplorerPageIds.Home), null); } } else if (prefix == "c:") { var vsGitServices = ServiceProvider.TryGetService <IVSGitServices>(); vsGitServices.SetDefaultProjectPath(newrepo.LocalPath); if (ErrorHandler.Succeeded(ServiceProvider.GetSolution().CreateNewProjectViaDlg(null, null, 0))) { ServiceProvider.TryGetService <ITeamExplorer>()?.NavigateToPage(new Guid(TeamExplorerPageIds.Home), null); } } }) ); #if DEBUG VsOutputLogger.WriteLine(String.Format(CultureInfo.InvariantCulture, "{0} Notification", DateTime.Now)); #endif }
void TryCleanupSolutionUserFiles(IOperatingSystem os, string repoPath, string slnName) { var vsTempPath = Path.Combine(repoPath, ".vs", slnName); try { // Clean up the dummy solution's subdirectory inside `.vs`. var vsTempDir = os.Directory.GetDirectory(vsTempPath); if (vsTempDir.Exists) { vsTempDir.Delete(true); } } catch (Exception e) { VsOutputLogger.WriteLine("Couldn't clean up {0}. {1}", vsTempPath, e); } }
/// <summary>Open a repository in Team Explorer</summary> /// <remarks> /// There doesn't appear to be a command that directly opens a target repo. /// Our workaround is to create, open and delete a solution in the repo directory. /// This triggers an event that causes the target repo to open. ;) /// </remarks> /// <param name="repoPath">The path to the repository to open</param> /// <returns>True if a transient solution was successfully created in target directory (which should trigger opening of repository).</returns> public bool TryOpenRepository(string repoPath) { var os = serviceProvider.TryGetService <IOperatingSystem>(); if (os == null) { VsOutputLogger.WriteLine("TryOpenRepository couldn't find IOperatingSystem service."); return(false); } var dte = serviceProvider.TryGetService <DTE>(); if (dte == null) { VsOutputLogger.WriteLine("TryOpenRepository couldn't find DTE service."); return(false); } var repoDir = os.Directory.GetDirectory(repoPath); if (!repoDir.Exists) { return(false); } bool solutionCreated = false; try { dte.Solution.Create(repoPath, TempSolutionName); solutionCreated = true; dte.Solution.Close(false); // Don't create a .sln file when we close. } catch (Exception e) { VsOutputLogger.WriteLine("Error opening repository. {0}", e); } finally { TryCleanupSolutionUserFiles(os, repoPath, TempSolutionName); } return(solutionCreated); }
async void UIContextChanged(bool active, bool refresh) { Debug.Assert(ServiceProvider != null, "UIContextChanged called before service provider is set"); if (ServiceProvider == null) { return; } if (active) { GitService = GitService ?? ServiceProvider.GetServiceSafe <IGitExt>(); if (ActiveRepo == null || refresh) { ActiveRepo = await System.Threading.Tasks.Task.Run(() => { var repos = GitService?.ActiveRepositories; // Looks like this might return null after a while, for some unknown reason // if it does, let's refresh the GitService instance in case something got wonky // and try again. See issue #23 if (repos == null) { VsOutputLogger.WriteLine(string.Format(CultureInfo.CurrentCulture, "Error 2001: ActiveRepositories is null. GitService: '{0}'", GitService)); GitService = ServiceProvider?.GetServiceSafe <IGitExt>(); repos = GitService?.ActiveRepositories; if (repos == null) { VsOutputLogger.WriteLine(string.Format(CultureInfo.CurrentCulture, "Error 2002: ActiveRepositories is null. GitService: '{0}'", GitService)); } } return(repos?.FirstOrDefault()?.ToModel()); }); } } else { ActiveRepo = null; } }
static void ForgetWithLogging(Task task) { task.Catch(e => VsOutputLogger.WriteLine("Exception caught while executing background task: {0}", e)).Forget(); }
void OnPropertyChange(object sender, PropertyChangedEventArgs e) { if (e.PropertyName == "IsVisible" && IsVisible && View == null) { View = new GitHubConnectContent { DataContext = this } } ; } async void UpdateRepositoryList(object sender, NotifyCollectionChangedEventArgs e) { if (e.Action == NotifyCollectionChangedAction.Add) { // if we're cloning or creating, only one repo will be added to the list // so we can handle just one new entry separately if (isCloning || isCreating) { var newrepo = e.NewItems.Cast <ISimpleRepositoryModel>().First(); SelectedRepository = newrepo; if (isCreating) { HandleCreatedRepo(newrepo); } else { HandleClonedRepo(newrepo); } var repo = await ApiFactory.Create(newrepo.CloneUrl).GetRepository(); newrepo.SetIcon(repo.Private, repo.Fork); } // looks like it's just a refresh with new stuff on the list, update the icons else { e.NewItems .Cast <ISimpleRepositoryModel>() .ForEach(async r => { if (Equals(Holder.ActiveRepo, r)) { SelectedRepository = r; } var repo = await ApiFactory.Create(r.CloneUrl).GetRepository(); r.SetIcon(repo.Private, repo.Fork); }); } } } void HandleCreatedRepo(ISimpleRepositoryModel newrepo) { var msg = string.Format(CultureInfo.CurrentUICulture, Constants.Notification_RepoCreated, newrepo.Name, newrepo.CloneUrl); msg += " " + string.Format(CultureInfo.CurrentUICulture, Constants.Notification_CreateNewProject, newrepo.LocalPath); ShowNotification(newrepo, msg); } void HandleClonedRepo(ISimpleRepositoryModel newrepo) { var msg = string.Format(CultureInfo.CurrentUICulture, Constants.Notification_RepoCloned, newrepo.Name, newrepo.CloneUrl); if (newrepo.HasCommits() && newrepo.MightContainSolution()) { msg += " " + string.Format(CultureInfo.CurrentUICulture, Constants.Notification_OpenProject, newrepo.LocalPath); } else { msg += " " + string.Format(CultureInfo.CurrentUICulture, Constants.Notification_CreateNewProject, newrepo.LocalPath); } ShowNotification(newrepo, msg); } void ShowNotification(ISimpleRepositoryModel newrepo, string msg) { var vsservices = ServiceProvider.GetExportedValue <IVSServices>(); vsservices.ClearNotifications(); vsservices.ShowMessage( msg, new RelayCommand(o => { var str = o.ToString(); /* the prefix is the action to perform: * u: launch browser with url * c: launch create new project dialog * o: launch open existing project dialog */ var prefix = str.Substring(0, 2); if (prefix == "u:") { OpenInBrowser(ServiceProvider.TryGetService <IVisualStudioBrowser>(), new Uri(str.Substring(2))); } else if (prefix == "o:") { if (ErrorHandler.Succeeded(ServiceProvider.GetSolution().OpenSolutionViaDlg(str.Substring(2), 1))) { ServiceProvider.TryGetService <ITeamExplorer>()?.NavigateToPage(new Guid(TeamExplorerPageIds.Home), null); } } else if (prefix == "c:") { vsservices.SetDefaultProjectPath(newrepo.LocalPath); if (ErrorHandler.Succeeded(ServiceProvider.GetSolution().CreateNewProjectViaDlg(null, null, 0))) { ServiceProvider.TryGetService <ITeamExplorer>()?.NavigateToPage(new Guid(TeamExplorerPageIds.Home), null); } } }) ); #if DEBUG VsOutputLogger.WriteLine(String.Format(CultureInfo.InvariantCulture, "{0} Notification", DateTime.Now)); #endif } void RefreshRepositories() { connectionManager.RefreshRepositories(); RaisePropertyChanged("Repositories"); // trigger a re-check of the visibility of the listview based on item count }
internal static string SetDefaultProjectPath(string path) { var old = String.Empty; try { var newProjectKey = Microsoft.Win32.Registry.CurrentUser.OpenSubKey(NewProjectDialogKeyPath, true) ?? Microsoft.Win32.Registry.CurrentUser.CreateSubKey(NewProjectDialogKeyPath); if (newProjectKey == null) { throw new GitHubLogicException( string.Format( CultureInfo.CurrentCulture, "Could not open or create registry key '{0}'", NewProjectDialogKeyPath)); } using (newProjectKey) { var mruKey = newProjectKey.OpenSubKey(MRUKeyPath, true) ?? Microsoft.Win32.Registry.CurrentUser.CreateSubKey(MRUKeyPath); if (mruKey == null) { throw new GitHubLogicException( string.Format( CultureInfo.CurrentCulture, "Could not open or create registry key '{0}'", MRUKeyPath)); } using (mruKey) { // is this already the default path? bail old = (string)mruKey.GetValue("Value0", string.Empty, RegistryValueOptions.DoNotExpandEnvironmentNames); if (String.Equals(path.TrimEnd('\\'), old.TrimEnd('\\'), StringComparison.CurrentCultureIgnoreCase)) { return(old); } // grab the existing list of recent paths, throwing away the last one var numEntries = (int)mruKey.GetValue("MaximumEntries", 5); var entries = new List <string>(numEntries); for (int i = 0; i < numEntries - 1; i++) { var val = (string)mruKey.GetValue("Value" + i, String.Empty, RegistryValueOptions.DoNotExpandEnvironmentNames); if (!String.IsNullOrEmpty(val)) { entries.Add(val); } } newProjectKey.SetValue("LastUsedNewProjectPath", path); mruKey.SetValue("Value0", path); // bump list of recent paths one entry down for (int i = 0; i < entries.Count; i++) { mruKey.SetValue("Value" + (i + 1), entries[i]); } } } } catch (Exception ex) { VsOutputLogger.WriteLine(string.Format(CultureInfo.CurrentCulture, "Error setting the create project path in the registry '{0}'", ex)); } return(old); }
protected override void OnAttached() { base.OnAttached(); AssociatedObject.SelectionChanged += (s, e) => { if (e.AddedItems.Count > 0) { if (previousSelection == null) { previousSelection = AssociatedObject.SelectedItem; if (defaultValue == null) { var binding = GetBinding(); Debug.Assert(binding != null, "Cannot find ItemsSource binding. Did you configure it in the target Listbox?"); if (binding == null) { return; } defaultValue = PropertyPathHelper.GetValue(binding.ResolvedSource, binding.ResolvedSourcePropertyName); } var list = AssociatedObject.ItemsSource as IList; Debug.Assert(list != null, "ItemsSource data source is not an IList, cannot change it."); if (list == null) { return; } try { list.Insert(0, defaultValue); } catch (Exception ex) { #if DEBUG throw ex; #else VsOutputLogger.WriteLine(String.Format(CultureInfo.CurrentCulture, "Could not add default empty item to the bound ItemsSource data source - the collection does not allow insertion (or the type does not match). {0}", ex)); #endif } } else if (AssociatedObject.SelectedIndex == 0) { var list = AssociatedObject.ItemsSource as IList; Debug.Assert(list != null, "ItemsSource data source is not an IList, cannot change it."); Debug.Assert(list.Count > 0, "ItemsSource data source is empty, something went wrong."); if (list == null || list.Count == 0) { return; } if (list[0] == defaultValue) { list.RemoveAt(0); } } } if (e.RemovedItems.Count > 0) { if (e.RemovedItems[0] == defaultValue) { previousSelection = null; AssociatedObject.SelectedItem = null; } } }; }
/// <summary> /// Gets the currently active text view(s) from Visual Studio. /// </summary> /// <returns> /// Zero, one or two active <see cref="ITextView"/> objects. /// </returns> /// <remarks> /// This method will return a single text view for a normal code window, or a pair of text /// views if the currently active text view is a difference view in side by side mode, with /// the first item being the side that currently has focus. If there is no active text view, /// an empty collection will be returned. /// </remarks> protected IEnumerable <ITextView> GetCurrentTextViews() { var result = new List <ITextView>(); try { var serviceProvider = Package; var monitorSelection = (IVsMonitorSelection)serviceProvider.GetService(typeof(SVsShellMonitorSelection)); if (monitorSelection == null) { return(result); } object curDocument; if (ErrorHandler.Failed(monitorSelection.GetCurrentElementValue((uint)VSConstants.VSSELELEMID.SEID_DocumentFrame, out curDocument))) { return(result); } IVsWindowFrame frame = curDocument as IVsWindowFrame; if (frame == null) { return(result); } object docView = null; if (ErrorHandler.Failed(frame.GetProperty((int)__VSFPROPID.VSFPROPID_DocView, out docView))) { return(result); } if (docView is IVsDifferenceCodeWindow) { var diffWindow = (IVsDifferenceCodeWindow)docView; switch (diffWindow.DifferenceViewer.ViewMode) { case DifferenceViewMode.Inline: result.Add(diffWindow.DifferenceViewer.InlineView); break; case DifferenceViewMode.SideBySide: switch (diffWindow.DifferenceViewer.ActiveViewType) { case DifferenceViewType.LeftView: result.Add(diffWindow.DifferenceViewer.LeftView); result.Add(diffWindow.DifferenceViewer.RightView); break; case DifferenceViewType.RightView: result.Add(diffWindow.DifferenceViewer.RightView); result.Add(diffWindow.DifferenceViewer.LeftView); break; } result.Add(diffWindow.DifferenceViewer.LeftView); break; case DifferenceViewMode.RightViewOnly: result.Add(diffWindow.DifferenceViewer.RightView); break; } } else if (docView is IVsCodeWindow) { IVsTextView textView; if (ErrorHandler.Failed(((IVsCodeWindow)docView).GetPrimaryView(out textView))) { return(result); } var model = (IComponentModel)serviceProvider.GetService(typeof(SComponentModel)); var adapterFactory = model.GetService <IVsEditorAdaptersFactoryService>(); var wpfTextView = adapterFactory.GetWpfTextView(textView); result.Add(wpfTextView); } } catch (Exception e) { VsOutputLogger.WriteLine("Exception in InlineCommentNavigationCommand.GetCurrentTextViews(): {0}", e); } return(result); }