/// <summary> /// Adds the current RepositoryUrl to the recent repositories list. /// Builds the RepositoryOverview /// This method has to be called from the main thread. /// </summary> void MakeTreeAndUpdateRepoUrl(SubversionSearcher subversionSearcher, string repoUrl) { if (SubversionSearcher.IsReady(subversionSearcher)) { string repositoryUrlcp = repoUrl; try { string newHeadNodePath = subversionSearcher.GetLowestExistingHeadNodePath(repoUrl, subversionSearcher.HeadRevision); HeadNodePath = newHeadNodePath; repositoryUrlcp = Utils.JoinPaths(subversionSearcher.RepositoryUrl, newHeadNodePath); RepositoryOverview.BuildRepositoryOverview(subversionSearcher, HeadNodePath, subversionSearcher.HeadRevision); } catch (Exception ex) { Progress.ErrorLog(ex); MessageBox.Show(String.Format("Error: {0}", ex.Message)); } if (RecentRepositories.Contains(repositoryUrlcp)) { RecentRepositories.Remove(repositoryUrlcp); } RecentRepositories.Insert(0, repositoryUrlcp); while (RecentRepositories.Count > Settings.Instance.RepositoryHistoryLength) { RecentRepositories.RemoveAt(RecentRepositories.Count - 1); } RaisePropertyChanged("RecentRepositories"); Settings.Instance.RecentRepositories = RecentRepositories.ToList(); Settings.Instance.RepositoryUrl = repositoryUrlcp; RepositoryUrl = repositoryUrlcp; if (subversionSearcher.InSearch) { Progress.Log("Building repository overview.."); TreeRevision = subversionSearcher.HeadRevision; RepositoryOverview.BuildRepositoryOverview(subversionSearcher, HeadNodePath, TreeRevision); Progress.Log("Ready"); } } }
/// <summary> /// Builds the Repository overview at a certain revision /// </summary> /// <param name="subversionSearcher">SubversionSearcher object to use</param> /// <param name="path">Path relative to RepositoryUrl of subversionSearcher</param> /// <param name="revision">Revision at which to build</param> public void BuildRepositoryOverview(SubversionSearcher subversionSearcher, string path, long revision) { if (!SubversionSearcher.IsReady(subversionSearcher)) { Progress.DebugLog("Tried to build repository overview without an initialized SubversionSearcher"); return; } if (revision == currentTreeRevision && path == currentTreeHeadPath && object.ReferenceEquals(currentSubversionSearcherUsedForTree, subversionSearcher) && this.Items != null && this.Items.Count != 0) { return; } if (path == null || subversionSearcher.PathExistsAtRevision(path, revision) == false) { Progress.Log("{0} does not exist at revision {1}", path, revision); this.Items = new List <CheckableItem> { }; return; } IList <string> expandedNodes = new List <string>(); IList <string> checkedNodes = new List <string>(); if (path == currentTreeHeadPath) { // keeping the nodes that were expanded expanded if (this.Items != null && this.Items.Count > 0) { Queue <CheckableItem> togo = new Queue <CheckableItem>(); foreach (var item in this.Items) { togo.Enqueue(item); } while (togo.Count > 0) { var item = togo.Dequeue(); if (item.IsExpanded) { expandedNodes.Add(item.Path.Length > path.Length ? item.Path.Substring(path.Length).TrimStart('/') : ""); foreach (var c in item.Children) { togo.Enqueue(c); } } } } else { expandedNodes.Add(""); } // keeping the nodes that were checked if (this.Items != null && this.Items.Count > 0) { Queue <CheckableItem> togo = new Queue <CheckableItem>(); foreach (var item in this.Items) { togo.Enqueue(item); } while (togo.Count > 0) { var item = togo.Dequeue(); if (item.IsChecked == true) { checkedNodes.Add(item.Path.Length > path.Length ? item.Path.Substring(path.Length).TrimStart('/') : ""); } else if (item.IsChecked == null) { foreach (var c in item.Children) { togo.Enqueue(c); } } } } } else { expandedNodes.Add(""); } CheckableItem rootFolder = new CheckableItem(null, path, revision, SharpSvn.SvnNodeKind.Directory, mainViewModel); rootFolder.Children = mainViewModel.LoadHierarchy(path, revision, rootFolder); foreach (var item in expandedNodes) { var ci = rootFolder.GetItemByRelativePath(item); if (ci != null) { ci.IsExpanded = true; } } foreach (var item in checkedNodes) { var ci = rootFolder.GetItemByRelativePath(item); if (ci != null) { ci.IsChecked = true; } } this.Items = new List <CheckableItem> { rootFolder }; currentTreeRevision = revision; currentTreeHeadPath = path; currentSubversionSearcherUsedForTree = subversionSearcher; }
/// <summary> /// Has to run asyncronously because it invokes methods in main thread /// </summary> /// <param name="repoUrl"></param> async void TryLoadRepository(string repoUrl) { if (!currentlyLoadingRepository.CompareAndSet(false, true)) { return; // do nothing because one repository is already loading } _searchResultsViewModel.Reset(); _repositoryOverviewViewModel.Reset(); _filePreviewViewModel.Reset(); if (repoUrl == null || repoUrl.Length == 0) { if (subversionSearcher != null) { subversionSearcher.Close(); subversionSearcher = null; } return; } repoUrl = repoUrl.TrimEnd('/') + '/'; if (SubversionSearcher.IsReady(subversionSearcher) && repoUrl.StartsWith(subversionSearcher.RepositoryUrl)) { // were just in another directory of the same repository //_headNodePath = subversionSearcher.GetLowestExistingHeadNodePath(repoUrl, subversionSearcher.HeadRevision); App.Current.Dispatcher.Invoke(() => MakeTreeAndUpdateRepoUrl(subversionSearcher, repoUrl)); } else { // load other repository // close the old one if (SubversionSearcher.IsReady(subversionSearcher)) { subversionSearcher.Close(); Progress.Log("Switching Repository..."); } subversionSearcher = null; /// START trying to find credentials by and opening add credentials window if necessary Progress.Log("Finding credentials..."); bool useCredentials = true; SubversionSearcher.AuthenticationInfo info = SubversionSearcher.HasCredentials(repoUrl); for (int i = 0; i < 4; i++) { if (info.Successful) { if (i == 0) { useCredentials = false; } break; } else if ( info.ThrownException != null && ( info.ThrownException is SharpSvn.SvnAuthorizationException || info.ThrownException is SharpSvn.SvnRepositoryIOForbiddenException || info.ThrownException is SharpSvn.SvnAuthenticationException) || info.ThrownException?.InnerException != null && ( info.ThrownException.InnerException is SharpSvn.SvnAuthorizationException || info.ThrownException.InnerException is SharpSvn.SvnRepositoryIOForbiddenException || info.ThrownException.InnerException is SharpSvn.SvnAuthenticationException)) { // trying to make sense of sharpsvn's exceptions // opening credentials window if (i == 0) { info = SubversionSearcher.CheckCredentials(repoUrl, Settings.Instance.Username, Settings.Instance.Password); } else { Progress.Log("Wrong credentials"); var mrse = new ManualResetEvent(false); bool cancelled = false; App.Current.Dispatcher.Invoke(() => { OpenCredentialsWindow(res => { HandleCredentialsWindowResponse(res); cancelled = res.cancelled; mrse.Set(); }); }); mrse.WaitOne(); if (cancelled) { break; } info = SubversionSearcher.CheckCredentials(repoUrl, Settings.Instance.Username, Settings.Instance.Password); } } else { Progress.Log(String.Format("{0}\r\nSee error.log", info.ExceptionMessage)); break; } } // END trying to find credentials if (info.Successful) { Progress.Log("Loading Repository"); if (useCredentials) { // Use credentials from credentials window or file await Task.Run(() => { try { subversionSearcher = new SubversionSearcher(RepositoryUrl, Settings.Instance.Username, Settings.Instance.Password); } catch (Exception ex) { Progress.Log("Failed to initialize. See error.log"); Progress.ErrorLog(ex); } }); } else { // Use credentials from tortoise await Task.Run(() => { try { subversionSearcher = new SubversionSearcher(RepositoryUrl); } catch (Exception ex) { Progress.Log("Failed to initialize. See error.log"); Progress.ErrorLog(ex); } }); } App.Current.Dispatcher.Invoke(() => MakeTreeAndUpdateRepoUrl(subversionSearcher, repoUrl)); } } currentlyLoadingRepository.Set(false); }