public GetSubmoduleFullPath ( string localPath ) : string | ||
localPath | string | |
return | string |
private void UpdateSubmodulesList() { _previousUpdateTime = DateTime.Now; // Cancel any previous async activities: _submodulesStatusCTS.Cancel(); _submodulesStatusCTS.Dispose(); _submodulesStatusCTS = new CancellationTokenSource(); RemoveSubmoduleButtons(); toolStripButtonLevelUp.DropDownItems.Add(_loading.Text); // Start gathering new submodule information asynchronously. This makes a significant difference in UI // responsiveness if there are numerous submodules (e.g. > 100). var cancelToken = _submodulesStatusCTS.Token; string thisModuleDir = Module.WorkingDir; // First task: Gather list of submodules on a background thread. var updateTask = Task.Factory.StartNew(() => { // Don't access Module directly because it's not thread-safe. Use a thread-local version: GitModule threadModule = new GitModule(thisModuleDir); SubmoduleInfoResult result = new SubmoduleInfoResult(); // Add all submodules inside the current repository: foreach (var submodule in threadModule.GetSubmodulesLocalPaths().OrderBy(submoduleName => submoduleName)) { cancelToken.ThrowIfCancellationRequested(); var name = submodule; string path = threadModule.GetSubmoduleFullPath(submodule); if (Settings.DashboardShowCurrentBranch && !GitModule.IsBareRepository(path)) name = name + " " + GetModuleBranch(path); var smi = new SubmoduleInfo { Text = name, Path = path }; result.OurSubmodules.Add(smi); GetSubmoduleStatusAsync(smi, cancelToken); } if (threadModule.SuperprojectModule != null) { GitModule supersuperproject = threadModule.FindTopProjectModule(); if (threadModule.SuperprojectModule.WorkingDir != supersuperproject.WorkingDir) { var name = Path.GetFileName(Path.GetDirectoryName(supersuperproject.WorkingDir)); string path = supersuperproject.WorkingDir; if (Settings.DashboardShowCurrentBranch && !GitModule.IsBareRepository(path)) name = name + " " + GetModuleBranch(path); result.TopProject = new SubmoduleInfo { Text = name, Path = supersuperproject.WorkingDir }; GetSubmoduleStatusAsync(result.TopProject, cancelToken); } { string name; GitModule parentModule = threadModule.SuperprojectModule; string localpath = ""; if (threadModule.SuperprojectModule.WorkingDir != supersuperproject.WorkingDir) { parentModule = supersuperproject; localpath = threadModule.SuperprojectModule.WorkingDir.Substring(supersuperproject.WorkingDir.Length); localpath = PathUtil.GetDirectoryName(localpath.ToPosixPath()); name = localpath; } else name = Path.GetFileName(Path.GetDirectoryName(supersuperproject.WorkingDir)); string path = threadModule.SuperprojectModule.WorkingDir; if (Settings.DashboardShowCurrentBranch && !GitModule.IsBareRepository(path)) name = name + " " + GetModuleBranch(path); result.Superproject = new SubmoduleInfo { Text = name, Path = threadModule.SuperprojectModule.WorkingDir }; GetSubmoduleStatusAsync(result.Superproject, cancelToken); } var submodules = supersuperproject.GetSubmodulesLocalPaths().OrderBy(submoduleName => submoduleName); if (submodules.Any()) { string localpath = threadModule.WorkingDir.Substring(supersuperproject.WorkingDir.Length); localpath = PathUtil.GetDirectoryName(localpath.ToPosixPath()); foreach (var submodule in submodules) { cancelToken.ThrowIfCancellationRequested(); var name = submodule; string path = supersuperproject.GetSubmoduleFullPath(submodule); if (Settings.DashboardShowCurrentBranch && !GitModule.IsBareRepository(path)) name = name + " " + GetModuleBranch(path); bool bold = false; if (submodule == localpath) { result.CurrentSubmoduleName = threadModule.GetCurrentSubmoduleLocalPath(); bold = true; } var smi = new SubmoduleInfo { Text = name, Path = path, Bold = bold }; result.SuperSubmodules.Add(smi); GetSubmoduleStatusAsync(smi, cancelToken); } } } return result; }, cancelToken); // Second task: Populate toolbar menu on UI thread. Note further tasks are created by // CreateSubmoduleMenuItem to update images with submodule status. updateTask.ContinueWith((task) => { if (task.Result == null) return; RemoveSubmoduleButtons(); var newItems = new List<ToolStripItem>(); task.Result.OurSubmodules.ForEach(submodule => newItems.Add(CreateSubmoduleMenuItem(submodule))); if (task.Result.OurSubmodules.Count == 0) newItems.Add(new ToolStripMenuItem(_noSubmodulesPresent.Text)); if (task.Result.Superproject != null) { newItems.Add(new ToolStripSeparator()); if (task.Result.TopProject != null) newItems.Add(CreateSubmoduleMenuItem(task.Result.TopProject, _topProjectModuleFormat.Text)); newItems.Add(CreateSubmoduleMenuItem(task.Result.Superproject, _superprojectModuleFormat.Text)); task.Result.SuperSubmodules.ForEach(submodule => newItems.Add(CreateSubmoduleMenuItem(submodule))); } newItems.Add(new ToolStripSeparator()); var mi = new ToolStripMenuItem(updateAllSubmodulesToolStripMenuItem.Text); mi.Click += UpdateAllSubmodulesToolStripMenuItemClick; newItems.Add(mi); if (task.Result.CurrentSubmoduleName != null) { var usmi = new ToolStripMenuItem(_updateCurrentSubmodule.Text); usmi.Tag = task.Result.CurrentSubmoduleName; usmi.Click += UpdateSubmoduleToolStripMenuItemClick; newItems.Add(usmi); } // Using AddRange is critical: if you used Add to add menu items one at a // time, performance would be extremely slow with many submodules (> 100). toolStripButtonLevelUp.DropDownItems.AddRange(newItems.ToArray()); _previousUpdateTime = DateTime.Now; }, cancelToken, TaskContinuationOptions.OnlyOnRanToCompletion, TaskScheduler.FromCurrentSynchronizationContext()); }